As parameters of types => T and () => T are both Function0, I always naively assumed that conversion from one to another is a noop. It seems however, that while true for (=>T) => (() => T), the other direction (() => T) => (=> T) results in wrapping the execution of the function in a invokedynamic lambda - at least as far as I can read the byte code.
Why?
How can I make it stop?
Related
I am working through the red book and when checking my answers for the exercises , I found that the solution for one of the exercises (6.11) was quite different (and much more elegant and cryptic than my own solution).
Here is the code:
object Candy {
def update: Input => Machine => Machine = (i: Input) => (s: Machine) =>
(i, s) match {
case (_, Machine(_, 0, _)) => s
case (Coin, Machine(false, _, _)) => s
case (Turn, Machine(true, _, _)) => s
case (Coin, Machine(true, candy, coin)) =>
Machine(false, candy, coin + 1)
case (Turn, Machine(false, candy, coin)) =>
Machine(true, candy - 1, coin)
}
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = for {
_ <- State.sequence(inputs map (modify[Machine] _ compose update))
s <- get
} yield (s.coins, s.candies)
def modify[S](f: S => S): State[S, Unit] = for {
s <- get // Gets the current state and assigns it to `s`.
_ <- set(f(s)) // Sets the new state to `f` applied to `s`.
} yield ()
def get[S]: State[S, S] = State(s => (s, s))
def set[S](s: S): State[S, Unit] = State(_ => ((), s))
The bit I am unsure of is this line:
inputs map (modify[Machine] _ compose update)
I understand how compose works but this particular syntax is really throwing me for a loop. Is there a way that this can be rewritten that is not so compact that would help a noob understand?
Thanks in advance.
Also for anyone else trying to better understand how this code works, this post I found helpful.
There are a couple of syntax features in use here:
Operator Syntax
Scala allows message sends to use whitespace instead of a period as the message sending operator, i.e.
foo.bar(baz, quux)
can also be written as
foo bar(baz, quux)
Operator Syntax, part 2
When using operator syntax with a single argument list with a single argument, the parentheses can be left off, i.e.
foo bar(baz)
can also be written as
foo bar baz
Placeholder syntax
Anonymous functions in Scala can be written using the underscore _ as a placeholder for the arguments. Roughly speaking, each underscore is replaced with each argument for the closest lexically enclosing anonymous function, in order of appearance in the source text, i.e.
val adder: (Int, Int) => Int = (x, y) => x + y
can also be written as
val adder: (Int, Int) => Int = _ + _
NOT η-expansion
The underscore _ has many uses in Scala, so sometimes if you don't look careful enough, you might confuse different usages. In this case, at a cursory glance, it seems like the underscore _ could mean that modify is η-expanded into a method value, but that is not the case. The underscore _ is an anonymous function argument placeholder.
Conclusion
So, if we put the above three syntax features together, the snippet in question desugars to
inputs.map(
// ↑ Operator Syntax
(
f => modify[Machine](f)
// ↑ Placeholder Syntax ↑
).compose(update)
// ↑ Operator Syntax
)
If you ever have doubts about what the syntax of a particular piece of code means, you can print out the internal state of the Scala compiler or the Scala REPL / "interpreter" at various phases using the -Xprint:<name-of-phase> command line option to scala. For example, this is what -Xprint:parser prints for the snippet in question:
inputs.map((modify[Machine]: (() => <empty>)).compose(update))
And this is -Xprint:typer:
inputs.map[this.State[this.Machine, Unit]](
(
(f: this.Machine => this.Machine) => $anon.this.State.modify[this.Machine](f)
).compose[this.Input](Candy.this.update)
)
Happened to stumble upon this. For anyone reading this, the underscore in inputs map (modify[Machine] _ compose update) is eta expansion, ie the _ translates the method into a function allowing this to be further composed to create a function of the form Input => State[Machine, Unit].
val t: Function1[Input, State[Machine, Unit]] = modify[Machine] _ compose update
Note that in scala3, this eta expansion takes place automagically and the _ syntax is not needed.
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 going through the book "Functional Programming in Scala" and have run across an example that I don't fully understand.
In the chapter on strictness/laziness the authors describe the construction of Streams and have code like this:
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]) : Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
...
}
The question I have is in the smart constructor (cons) where it calls the constructor for the Cons case class. The specific syntax being used to pass the head and tail vals doesn't make sense to me. Why not just call the constructor like this:
Cons(head, tail)
As I understand the syntax used it is forcing the creation of two Function0 objects that simply return the head and tail vals. How is that different from just passing head and tail (without the () => prefix) since the Cons case class is already defined to take these parameters by-name anyway? Isn't this redundant? Or have I missed something?
The difference is in => A not being equal to () => A.
The former is pass by name, and the latter is a function that takes no parameters and returns an A.
You can test this out in the Scala REPL.
scala> def test(x: => Int): () => Int = x
<console>:9: error: type mismatch;
found : Int
required: () => Int
def test(x: => Int): () => Int = x
^
Simply referencing x in my sample causes the parameter to be invoked. In your sample, it's constructing a method which defers invocation of x.
First, you are assuming that => A and () => A are the same. However, they are not. For example, the => A can only be used in the context of passing parameters by-name - it is impossible to declare a val of type => A. As case class parameters are always vals (unless explicitly declared vars), it is clear why case class Cons[+A](h: => A, t: => Stream[A]) would not work.
Second, just wrapping a by-name parameter into a function with an empty parameter list is not the same as what the code above accomplishes: using lazy vals, it is ensured that both hd and tl are evaluated at most once. If the code read
Cons(() => hd, () => tl)
the original hd would be evaluated every time the h method (field) of a Cons object is invoked. Using a lazy val, hd is evaluated only the first time the h method of this Cons object is invoked, and the same value is returned in every subsequent invocation.
Demonstrating the difference in a stripped-down fashion in the REPL:
> def foo = { println("evaluating foo"); "foo" }
> val direct : () => String = () => foo
> direct()
evaluating foo
res6: String = foo
> direct()
evaluating foo
res7: String = foo
> val lzy : () => String = { lazy val v = foo; () => v }
> lzy()
evaluating foo
res8: String = foo
> lzy()
res9: String = foo
Note how the "evaluating foo" output in the second invocation of lzy() is gone, as opposed to the second invocation of direct().
Note that the parameters of the method cons are by-name parameters (hd and tl). That means that if you call cons, the arguments will not be evaluated before you call cons; they will be evaluated later, at the moment you use them inside cons.
Note that the Cons constructor takes two functions of type Unit => A, but not as by-name parameters. So these will be evaluated before you call the constructor.
If you do Cons(head, tail) then head and tail will be evaluated, which means hd and tl will be evaluated.
But the whole point here was to avoid calling hd and tl until necessary (when someone accesses h or t in the Cons object). So, you pass two anonymous functions to the Cons constructor; these functions will not be called until someone accesses h or t.
In def cons[A](hd: => A, tl: => Stream[A]) : Stream[A]
the type of hd is A, tl is Stream[A]
whereas in case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
h is of type Function0[A] and t of type Function0[Stream[A]]
given the type of hd is A, the smart constructor invokes the case class as
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail) //it creates a function closure so that head is accessible within Cons for lazy evaluation
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(_())
In the following code snippet, what does (F: => T) mean?
def func1[T](arg1: Int, arg2: String)(F: => T): func2[T]
Thanks
F is the argument name; => T means it's a by-name parameter. It's basically equivalent to () => T with some syntactic sugar:
When invoking this method, the argument will have type T and will automatically be turned into () => T:
func1[String](0, x)(x + x) ===> func1[String](0, x)(() => x + x)
When implementing this method, each use of F turns into F(). So the value of type T will be recalculated each time.
Obviously, this is useful in one of two cases:
if F may not be needed;
if the value returned by F may change between different invocations.