I am trying to understand the following code but can't.
it is supposed to create a child actor for an Event if it does not exist, otherwise says that the Event exist as it as an associated child actor.
context.child(name).fold(create())(_ => sender() ! EventExists)
But the fold here does not make sense to me. If the context.child is emtpty we get the creation and i understand that. However if there is children we are still going to create why ?
Akka's child returns an Option
As you can see from Option's scaladoc:
fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B Returns the result of
applying f to this scala.Option's value if the scala.Option is
nonempty. Otherwise, evaluates expression ifEmpty.
Or making it more clear:
This (fold) is equivalent to scala.Option map f getOrElse ifEmpty.
So the first parameter of fold is lazy (call-by-name) and evaluates only if Option is empty. The second parameter (a function) is called only if Option is not empty.
Experiment:
scala> Some(0).fold({println("1");1}){_ => println("2"); 2}
2
res0: Int = 2
scala> None.fold({println("1");1}){_ => println("2"); 2}
1
res1: Int = 1
Here's some readings about:
https://kwangyulseo.com/2014/05/21/scala-option-fold-vs-option-mapgetorelse/
And some critics of that approach:
http://www.nurkiewicz.com/2014/06/optionfold-considered-unreadable.html
But in Option.fold() the contract is different: folding function takes
just one parameter rather than two. If you read my previous article
about folds you know that reducing function always takes two
parameters: current element and accumulated value (initial value
during first iteration). But Option.fold() takes just one parameter:
current Option value! This breaks the consistency, especially when
realizing Option.foldLeft() and Option.foldRight() have correct
contract (but it doesn't mean they are more readable).
Related
Folding list in scala using /: and :\ operator
I tried to to look at different sites and they only talk about foldRight and foldLeft functions.
def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)
sum(List(1,2,3))
res0: 6
The code segment works as described. But I am not able to completely understand the method definition. What I understand is that the one inside the first parenthesis -> 0 /: xs where /: is a right associate operator. The object is xs and the parameter is 0. I am not sure about the return type of the operation (most probably it would be another list?). The second part is a functional piece which sums its two parameters. But I don't understand what object invokes it ? and the name of function. Can someone please help me to understand.
The signature of :/ is
/:[B](z: B)(op: (B, A) ⇒ B): B
It is a method with multiple argument lists, so when it is just invoked with on argument (i.e. 0 /: xs in your case) the return type is (op: (B, A) ⇒ B): B. So you have to pass it a method with 2 parameters ( _ + _ ) that is used to combine the elements of the list starting from z.
This method is usually called foldLeft:
(0 /: xs)(_ + _) is the same as xs.foldLeft(0)(_ + _)
You can find more details here: https://www.scala-lang.org/api/2.12.3/scala/collection/immutable/List.html
Thanks #HaraldGliebe & #LuisMiguelMejíaSuárez for your great responses. I am enlightened now!. I am just summarisig the answer here which may benefit others who read this thread.
"/:" is actually the name of the function which is defined inside the List class. The signature of the function is: /:[B](z: B)(op: (B, A) ⇒ B): B --> where B is the type parameter, z is the first parameter; op is the second parameter which is of functional type.
The function follows curried version --> which means we can pass less number of parameters than that of the actual number. If we do that,
the partially applied function is stored in a temporary variable; we can then use the temporary variable to pass the remaining parameters.
If supplied with all parameters, "/:" can be called as: x./:(0)(_+_) where x is val/var of List type. OR "/:" can be called in two steps which are given as:
step:1 val temp = x./:(0)(_) where we pass only the first parameter. This results in a partially applied function which is stored in the temp variable.
step:2 temp(_+_) here using the partially applied function temp is passed with the second (final) parameter.
If we decide to follow the first style ( x./:(0)(_+_) ), calling the first parameter can be written in operator notion which is: x /: 0
Since the method name ends with a colon, the object will be pulled from right side. So x /: 0 is invalid and it has to be written as 0 /: x which is correct.
This one is equivalent to the temp variable. On following 0 /: x, second parameter also needs to be passed. So the whole construct becomes: (0/:x)(_+_)
This is how the definition of the function sum in the question, is interpreted.
We have to note that when we use curried version of the function in operator notion, we have to supply all the parameters in a single go.
That is: (0 /: x) (_) OR (0 /: x) _ seems throwing syntax errors.
The scala documentation has a code example that includes the following line:
val numberFunc = numbers.foldLeft(List[Int]())_
What does the underscore after the method call mean?
It's a partially applied function. You only provide the first parameter to foldLeft (the initial value), but you don't provide the second one; you postpone it for later. In the docs you linked they do it in the next line, where they define squares:
val numberFunc = numbers.foldLeft(List[Int]())_
val squares = numberFunc((xs, x) => xs:+ x*x)
See that (xs, x) => xs:+ x*x, that's the missing second parameter which you omitted while defining numberFunc. If you had provided it right away, then numberFunc would not be a function - it would be the computed value.
So basically the whole thing can also be written as a one-liner in the curried form:
val squares = numbers.foldLeft(List[Int]())((xs, x) => xs:+ x*x)
However, if you want to be able to reuse foldLeft over and over again, having the same collection and initial value, but providing a different function every time, then it's very convinient to define a separate numbersFunc (as they did in the docs) and reuse it with different functions, e.g.:
val squares = numberFunc((xs, x) => xs:+ x*x)
val cubes = numberFunc((xs, x) => xs:+ x*x*x)
...
Note that the compiler error message is pretty straightforward in case you forget the underscore:
Error: missing argument list for method foldLeft in trait
LinearSeqOptimized Unapplied methods are only converted to functions
when a function type is expected. You can make this conversion
explicit by writing foldLeft _ or foldLeft(_)(_) instead of
foldLeft. val numberFunc = numbers.foldLeft(ListInt)
EDIT: Haha I just realized that they did the exact same thing with cubes in the documentation.
I don't know if it helps but I prefer this syntax
val numberFunc = numbers.foldLeft(List[Int]())(_)
then numberFunc is basically a delegate corresponding to an instance method (instance being numbers) waiting for a parameter. Which later comes to be a lambda expression in the scala documentation example
An infinite stream:
val ones: Stream[Int] = Stream.cons(1, ones)
How is it possible for a value to be used in its own declaration? It seems this should produce a compiler error, yet it works.
It's not always a recursive definition. This actually works and produces 1:
val a : Int = a + 1
println(a)
variable a is created when you type val a: Int, so you can use it in the definition. Int is initialized to 0 by default. A class will be null.
As #Chris pointed out, Stream accepts => Stream[A] so a bit another rules are applied, but I wanted to explain general case. The idea is still the same, but the variable is passed by-name, so this makes the computation recursive. Given that it is passed by name, it is executed lazily. Stream computes each element one-by-one, so it calls ones each time it needs next element, resulting in the same element being produces once again. This works:
val ones: Stream[Int] = Stream.cons(1, ones)
println((ones take 10).toList) // List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
Though you can make infinite stream easier: Stream.continually(1) Update As #SethTisue pointed out in the comments Stream.continually and Stream.cons are two completely different approaches, with very different results, because cons takes A when continually takes =>A, which means that continually recomputes each time the element and stores it in the memory, when cons can avoid storing it n times unless you convert it to the other structure like List. You should use continually only if you need to generate different values. See #SethTisue comment for details and examples.
But notice that you are required to specify the type, the same as with recursive functions.
And you can make the first example recursive:
lazy val b: Int = b + 1
println(b)
This will stackoverflow.
Look at the signature of Stream.cons.apply:
apply[A](hd: A, tl: ⇒ Stream[A]): Cons[A]
The ⇒ on the second parameter indicates that it has call-by-name semantics. Therefore your expression Stream.cons(1, ones) is not strictly evaluated; the argument ones does not need to be computed prior to being passed as an argument for tl.
The reason this does not produce a compiler error is because both Stream.cons and Cons are non-strict and lazily evaluate their second parameter.
ones can be used in it's own definition because the object cons has an apply method defined like this:
/** A stream consisting of a given first element and remaining elements
* #param hd The first element of the result stream
* #param tl The remaining elements of the result stream
*/
def apply[A](hd: A, tl: => Stream[A]) = new Cons(hd, tl)
And Cons is defined like this:
final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A]
Notice that it's second parameter tl is passed by name (=> Stream[A]) rather than by value. In other words, the parameter tl is not evaluated until it is used in the function.
One advantage to using this technique is that you can compose complex expressions that may be only partially evaluated.
I have the following Code.
import scala.collection.mutable.MutableList
val x = MutableList[Int]()
(1 to 10).foreach(x+=1)
I get the java.lang.IndexOutOfBoundsException: 1 error.
but,
(1 to 10).foreach(println) this does not throw any error.
the indexOutOfBoundException can be solved by using lambda Operator as follows:
(1 to 10).foreach(_ => x+=1)
Everything works fine with this.
My questions are :
1. Why do i need to use lambda operator in first case unlike second one?
2. Why the compiler throws IndexOutOfBoundException, i suppose this is not the correct context for this Exception.
What happens is a few little conveniences in the library conspiring to bite you.
foreach signature is
def foreach(f: A => Unit): Unit
In your case, A is Int, so it needs a function which takes an Int and returns Unit. Fine with println. Note you have just written println, not println(something), which would not have been a function.
One would expect x += 1 to be just an instruction, so it would have type Unit, not a function, not a valid argument of foreach, and one would get a helpful compile-time error. But += in MutableList actually returns the list, which is convenient as it makes chaining operations easier:
def +=(elem: A): this.type
So the type of x+= 1 is MutableList[Int]. One will still expect a compilation error, not a function. Except that MutableLists (all Seqs actually) are functions, with Int parameters, returning the type of the Seq's elements. The function simply returns the i-th element. Again, that may be convenient, you may simply pass the seq where a function is expected, instead of having to write i => seq(i). Now you have a function, with an Int parameter, what foreach expects.
Still, it does not returns Unit, but Int. However, scala will accept that as an Int => Unit, just discarding the value. So it compiles.
Now to what it does: first, it evaluates the argument in foreach, so it calls x+=1, getting the list x, which now contains an element. It will then call this function, which is the access to the i-th element with arguments ranging from 1 to 10). Doing that, it would not add values to the list, but just access elements at the given indexes. It then fails immediately, as the list contains just one element, at index 0, so calling with 1 throws the IndexOutOfBoundException.
I have two functions (not these have been edited since the original -- some of the answers below are responding to the original ones which returned a sequence of ()):
def foo1[A](ls: Iterable[A]) : Iterator[A] =
for (List(a, b) <- ls sliding 2) yield a
def foo2[A](ls: Iterable[A]) : Iterator[A] =
for (a::b::Nil <- ls sliding 2) yield a
which I naively thought were the same. But Scala gives this waning only for the first one:
warning: non variable type-argument A in type pattern List[A]
is unchecked since it is eliminated by erasure
I think I understand why it gives that error for the first one: Scala thinks that I'm trying to use the type as a condition on the pattern, ie a match against List[B](_, _) should fail if B does not inherit from A, except that this can't happen because the type is erased in both cases.
So two questions:
1) Why does the second one not give the same warning?
2) Is it possible to convince Scala that the type is actually known at compile time, and thus can't possibly fail to match?
edit: I think this answers my first question. But I'm still curious about the second one.
edit: agilesteel mentioned in a comment that
for (List(a, b) <- List(1,2,3,4) sliding 2) yield ()
produces no warning. How is that different from foo1 (shouldn't the [Int] parameter be erased just the same as the [A] parameter is)?
I'm not sure what is happening here, but the static type of Iterable[A].sliding is Iterator[Iterable[A]], not Iterator[List[A]] which would be the static type of List[A].sliding.
You can try receiving Seq instead of Iterable, and that work too. EDIT Contrary to what I previously claimed, both Iterable and Seq are co-variant, so I don't know what's different. END EDIT The definition of sliding is pretty weird too:
def sliding [B >: A] (size: Int): Iterator[Iterable[A]]
See how it requires a B, superclass of A, that never gets used? Contrast that with an Iterator.sliding, for which there's no problem:
def sliding [B >: A] (size: Int, step: Int = 1): GroupedIterator[B]
Anyway, on to the second case:
for (a::b::Nil <- ls sliding 2) yield a
Here you are decomposing the list twice, and for each decomposition the type of head is checked against A. Since the type of head is not erased, you don't have a problem. This is also mostly a guess.
Finally, if you turn ls into a List, you won't have a problem. Short of that, I don't think there's anything you can do. Otherwise, you can also write this:
def foo1[A](ls: Iterable[A]) : Iterator[A] =
for (Seq(a, b) <- ls.iterator sliding 2) yield a
1) The second one does not produce a warning probably because you are constructing the list (or the pattern) by prepending elements to the Nil object, which extends List parameterising it with Nothing. And since everything is Nothing, there is nothing to be worried about ;) But I'm not sure, really guessing here.
2) Why don't you just use:
def foo[A](ls: Iterable[A]) =
for (list <- ls sliding 2) yield ()