Could someone please explain this piece of code:
val ns: Iterator[Int] = (1 to 3).iterator
ns.map(_ => () => block)
where
block: => Future[T]
Basically I'm just confused about what's going on with the _, =>, and Unit () syntax. The way I am trying to read it is 'we map a function which returns a function that takes no params and returns a Future[T] over the list of integers'. Is this correct? I'm always confused when I see multiple => operators in a row..
Yes, you are correct.
It's parsed like this:
ns.map(_ => (() => block))
And the () => ? syntax is just defining a parameterless function:
val f = () => 1
f() // 1
So the integer in ns is ignored, and you just get an iterator of functions that take no parameters and return Futures: Iterator[() => Future[T]].
I think this block: => Future[T] maybe the signature of the method. It means call-by-name. Basically, you can understand that it is just a type Future[T] which is lazy evaluated but not a function
val ns: Iterator[Int] = (1 to 3).iterator
ns.map(_ => () => block)
This will return Iterator[() => Future], so yes, you are right, this transform to a function which takes nothing to Future. The good thing of this is that it will not evaluate the Future immediately, it will be called when you invoked.
val result = ns.map(_ => () => block)
result.foreach(_())
Related
I am studying rxScal example at https://github.com/ReactiveX/RxScala/blob/0.x/examples/src/test/scala/examples/RxScalaDemo.scala
This example contains following code:
o.subscribe(
n => println(n),
e => e.printStackTrace(),
() => println("done")
)
But the signature of subscribe is:
def foreach(onNext: T => Unit, onError: Throwable => Unit): Unit = {
asJavaObservable.subscribe(onNext, onError)
}
I do not understand who renames onNext to n?
n => println(n) is an anonymous function (a function with no name) that takes an argument and acts on it. That argument is labeled n but it could have been x or wwz, or whatever.
When you pass that function as an argument to another function, the receiving function will give the received argument a name. The first argument to foreach is labeled onNext but it could have been x or zzw or whatever. It is the name of the received function. It doesn't matter what the name of that function was when it was passed to foreach, maybe it was anonymous and had no name, inside the foreach code it now has the name onNext.
Inside foreach, onNext is the name of a function that takes an argument and acts on it. The name of that argument is unknown and immaterial to the foreach code.
So, in short, onNext hasn't been renamed to n. They are, essentially, unrelated.
You have given the signature of foreach, not subscribe. It looks like the signature of subscribe is:
def subscribe(onNext: T => Unit, onError: Throwable => Unit, onComplete: Unit => Unit): Subscription
this means that
n => println(n)
is a function which is executed when the next value of T arrives. Therefore n has type T and is bound to the incoming value. Similarly
e => e.printStackTrace()
is a function Throwable => Unit so e has type Throwable and will be bound to the error parameter given to onError of the Observable.
Perhaps it will be clearer if we remove some of the Scala magic so we can think about the code in more deliberate steps:
def subscribe(onNext: AnyRef => Unit, onError: Throwable => Unit, onComplete: Unit => Unit): Subscription = ...
val myOnNext: AnyRef => Unit = n => println(n)
val myOnError: Throwable => Unit = e => e.printStackTrace()
val myOnComplete: Unit => Unit = _ => println("done")
o.subscribe(myOnNext, myOnError, myOnComplete)
I am trying to write a partially applied function. I thought the below would work but it doesn't. Grateful for any help.
scala> def doSth(f: => Unit) { f }
doSth: (f: => Unit)Unit
scala> def sth() = { println ("Hi there") }
sth: ()Unit
scala> doSth(sth)
Hi there
scala> val b = sth _
b: () => Unit = <function0>
scala> doSth(b)
<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
doSth(b)
^
Thanks!
The difference is subtle. sth is a method, so you can call it without the parentheses, which is what is happening here:
doSth(sth)
But b is just a function () => Unit, which you must use the parentheses to invoke.
doSth(b())
Otherwise you would not be able to assign b to another identifier.
val c: () => Unit = b
If we automatically invoked b here, c would be Unit instead of () => Unit. The ambiguity must be removed.
Let me also clarify that doSth is not a method that accepts only functions. f: => Unit means it accepts anything that evaluates to Unit, which includes methods that return Unit when they are invoked. doSth(sth) is not passing the message sth to doSth, it's invoking sth without parentheses and passing the result.
I think the difference is that b has type () => Unit, and doSth expects an expression that returns Unit (minor difference). If you want to store sth as a variable without the side effects, you could do:
lazy val b = sth
doSth(b)
The other option would be to make it so that doSth takes in () => Unit:
def doSth(f: () => Unit) { f() }
def sth() = { println ("Hi there") }
doSth(sth)
val b = sth _
doSth(b)
I'd like to be able to pass in callback functions as parameters to a method. Right now, I can pass in a function of signature () => Unit, as in
def doSomething(fn:() => Unit) {
//... do something
fn()
}
which is fine, I suppose, but I'd like to be able to pass in any function with any parameters and any return type.
Is there a syntax to do that?
Thanks
To be able to execute a function passed as a callback you have to be able to call it with the arguments it requires. f: A => R must be called as f(someA), and g: (A,B) => R must be called as f(someA, someB).
Implementing a callback you want a function that accepts a context and returns something (you don't care what the something is). For example foreach in scala.Option is defined as:
def foreach[U](f: (A) => U): Unit
The function is called with a value of type A but the result is discarded so we don't care what type it has. Alternatively if you don't care what was completed the callback function could be implemented as:
def onComplete[U](f: () => U): Unit
It would then allow being called with any function that takes no arguments:
val f: () => Int = ...
val g: () => String = ...
onComplete(f) // In result is discarded
onComplete(g) // String result is discarded
If you really wanted a function that accepted any possible function there are some tricks you could use (but you really shouldn't). For example you could define a view bound with implicit conversions:
// Type F is any type that can be converted to () => U
def onComplete[F <% () => U, U](f: F): Unit
// Define conversions for each Function type to Function0
implicit def f1tof0[A,U](f: A => U): () => U = ...
implicit def f2tof0[A,B,U](f: (A,B) => U): () => U = ...
implicit def f3tof0[A,B,C,U](f: (A,B,C) => U): () => U = ...
.
.
etc.
Now onComplete accepts any function:
val f: Int => String = ...
val g: (List[Int], String) => String = ...
onComplete(f)
onComplete(g)
Defining the types for the above conversions is relatively simple, but there is no rational way to implement them so is pretty much entirely useless.
I want to have a function that takes a variable number of functions, but I want them to not be evaluated until I actually used them. I could use the () => type syntax, but I would prefer to use the => type syntax, because it seems to be custom made for delaying evaluation.
When I try something like this:
def functions(fns: => String*) = "OK"
I get the error:
error: ')' expected but identifier found.
def functions(fns: => String*) = "OK"
Interestingly, it works fine when I change it to
def functions(fns: () => String*) = "OK"
What do I have to do to get my first function to work?
Since I submitted the issue:
https://issues.scala-lang.org/browse/SI-5787
It may yet happen.
Depending on your semantics, consider using Stream[String], which evaluates lazily.
def foo(i: Int): String = { println(s"Numbering $i"); s"Number $i" }
val invocations = foo(2) #:: foo(4) #:: foo(5) #:: foo(8) #:: Stream.empty
Edit: Then I thought, didn't someone just ask that? A couple of more answers here using implicits. I think my answer there should be up-voted just for "This used to happens first".
For now, you have to use () => X* for repeated parameters. This makes entering them a pain, so you may wish to
implicit def anything_to_function0[A](a: => A): () => A = () => a
scala> def functions(fns: () => String*) = fns.length
functions: (fns: () => String*)Int
scala> functions("salmon","cod")
res2: Int = 2
I'd like to implement validation for a sequence of operations that all return Either[Error,Item]
It should be fail-fast (in my initial need), I mean, returning Either[Error,Seq[Item]].
If there is an error, it's obvious i do not want the following operations to be performed.
But in the future i may want to collect all the errors instead of returning only the first one.
I know Scalaz can do the job but for now I quite don't understand all parts of Scalaz and I'm pretty sure there's a simpler way to do it without using Scalaz, but using by-name parameters for exemple.
Is there a way to store by-name parameters in a sequence?
So that i can create a sequence of by-name values that represent my operations?
I mean, some kind of type Seq[=> Either[Error,Item]]
Then I could do something like calling takeWhile or collectFirst or something somilar, without all the operations being performed before the creation of the sequence?
I would expect the operations to be performed only when iterating on the sequence.
Thanks
You can indeed use a Seq[() => Either[Error, Item]] to defer the computation at collection creation time. So for example
val doSomething1: () => Either[Error, Item] = () => { println(1); Right(1) }
val doSomething2: () => Either[Error, Item] = () => { println(2); Right(2) }
val doSomething3: () => Either[Error, Item] = () => { println(3); Left("error") }
val doSomething4: () => Either[Error, Item] = () => { println(4); Right(3) }
val doSomething5: () => Either[Error, Item] = () => { println(5); Left("second error") }
val l = Seq(doSomething1, doSomething2, doSomething3, doSomething4, doSomething5)
(Items are Ints in the example and Errors are Strings)
Then you can process them lazily stopping at first failure using the following recursive function:
def processUntilFailure(l: Seq[() => Either[Error, Item]]): Either[Error, Seq[Item]] = {
l.headOption.map(_.apply() match {
case Left(error) => Left(error)
case Right(item) => processUntilFailure(l.tail).right.map(_ :+ item)
}).getOrElse(Right(Nil))
}
So now when I run processUntilFailure(l)
scala> processUntilFailure(l)
1
2
3
res1: Either[Error,Seq[Item]] = Left(error)
If you wanted to generate a Either[Seq[String], Seq[Int]] (processing all the operations). You could do it with a little change:
def processAll(l: Seq[() => Either[Error, Item]]): Either[Seq[Error], Seq[Item]] = {
l.headOption.map(_.apply() match {
case Left(error) => processAll(l.tail) match {
case Right(_) => Left(Seq(error))
case Left(previousErrors) => Left(previousErrors :+ error)
}
case Right(item) => processAll(l.tail).right.map(_ :+ item)
}).getOrElse(Right(Nil))
}
The only change as you can see is the Left case in the pattern match. Running this one:
scala> processAll(l)
1
2
3
4
5
res0: Either[Seq[Error],Seq[Item]] = Left(List(second error, error))
processAll can be replaced with a generic foldLeft on l
val zero: Either[Seq[Error], Seq[Item]] = Right(Seq[Item]())
l.foldLeft(zero) { (errorsOrItems: Either[Seq[Error], Seq[Item]], computation: () => Either[String, Int]) =>
computation.apply().fold(
{ (error: String) => Left(errorsOrItems.left.toOption.map(_ :+ error).getOrElse(Seq(error))) },
{ (int: Int) => errorsOrItems.right.map(_ :+ int) })
}
processUntilFailure can as well but not easily. Since aborting early from a fold is tricky. Here's a good answer about other possible approaches when you find yourself needing to do that.
You should be able to pull this off with the type Seq[Function0[Either[Error, Item]]]. Function0 is, obviously, a zero-argument function. The rest should be self-explanatory.
Scalaz provides the type IO for exactly this purpose, so you could actually use that as well. You may not want to yet, however, if you're just beginning to work with Scalaz.