Scala Call By Name Confusion

I am working on some examples by name using REPL and running the same examples in Eclipse.

Here is what in Eclipse:
Scenario 1:

val funct = {println("Calling funct")} takesFunct(funct) def takesFunct(f: => Unit) { val b = f } 

Output: Call Function

Scenario 2:
getsFunct method remains the same

 takesFunct({println("Calling funct")} 

Exit:
Call Function Call Function

Scala REPL Scenario 1:

 scala> def takesFunct(f: => Unit) { val b = f } takesFunct: (f: => Unit)Unit scala> val funct = {println("Calling funct")} Calling funct funct: Unit = () scala> takesFunct(funct) // No Output 

Scenario 2 The same method as defined above

 scala> takesFunct({println("Calling funct")} Calling funct 

Two questions
1) Why is the output of Eclipse different from REPL?
2) What is the difference between passing in

 val funct = {...} takesFunct(funct) 

Unlike

 takesFunct({...}) 
+6
scala
source share
3 answers

Updated after @IttayD answer:

Scenario 1 on Eclipse is right, you will see why below. Scenario 2 is clearly an Eclipse bug. ScalaIDE on Eclipse is known for its weakness. I do not trust him (or use him). Use the Intellij IDEA Scala plugin if you need to.

The answer to both questions: {} is a block that returns the return type of the last statement. This is exactly the same as the scheme (begin) or Common Lisp (progn) . When you have:

 scala> def takesFunct(f: => Unit) { val b = f } takesFunct: (f: => Unit)Unit scala> val funct = {println("Calling funct")} Calling funct funct: Unit = () scala> takesFunct(funct) // No Output 

funct RHS is already evaluated with a high degree of accuracy and returns a value () type Unit . Applying an already calculated value to a call function and using it in the body does not cause revaluation because the value is already a sheet.

Further update:

 def takesFunct(f: => Unit) 

has essentially the same semantics as

 def takesFunct(f: () => Unit) 

which is known as streaming or deferred ratings in certain circles. However, there is one significant difference, which is how you refer to the provided argument. In the latter case, to return a value from f , you must call it as such - ie f() . In the first case, f is a β€œlazy" lazy expression that evaluates to the value when it is first referenced as such, therefore it is called by name. You can imagine the syntax f: => Unit as a way to automatically wrap any expression that you supply in the container {} . The contents of which are extracted when used as follows:

 scala> val a = { 1 } // 1 wrapped in {}, and retrieved when assigned to a a: Int = 1 

What about this one?

 scala> takesFunct({println("Calling funct")}) Calling funct 

This is due to the fact that now you create a block in place that is bound to the parameter of the function f , and it is evaluated only when you use it in val b = f . Do another experiment:

 scala> takesFunct(println("Calling funct")) Calling funct 

Why do you ask? Since println(...) was enclosed in {} bound to f . The f link retrieves the value inside the container, which is the println(...) value, which is equal to ():Unit . In the previous example, f was bound to { { println(...) } } , which is the same as { println(...) } , so you get the same result. In fact, you can invest {} indefinitely and still return the same. The only difference is that with manual delivery {} you can enter several statements inside:

 scala> takesFunct({ println("hello"); println("world") }) hello world 

Hope this helps.

+9
source share

There is no difference in the conclusion. The difference is what you want. From Eclipse, you used two things:

 val funct = {println("Calling funct")} // prints Calling funct here takesFunct(funct) def takesFunct(f: => Unit) { val b = f } 

and

 val funct = {println("Calling funct")} // prints Calling funct here takesFunct({println("Calling funct")} def takesFunct(f: => Unit) { val b = f // prints Calling funct here } 

In REPL, the same thing happened according to your own logs:

 scala> def takesFunct(f: => Unit) { val b = f } takesFunct: (f: => Unit)Unit scala> val funct = {println("Calling funct")} Calling funct funct: Unit = () scala> takesFunct(funct) // No Output 

Now in the second scenario, all you have done is:

 scala> takesFunct({println("Calling funct")} Calling funct 

Since you did not repeat the val funct that was still present in the second Eclipse script, it did not display a message.

note that

 val funct = {println("Calling funct")} 

as practical value is equivalent

 println("Calling funct") val funct = () 
+2
source share

Scenario 1: as expected. Exit the first line without calling the method.

Scenario 2: I do not have Eclipse, but it does not sound like that.

REPL Scenario 1: You cannot define a call by name. what you did is assign the last value of the expression {println("Calling funct")} to the function. This last value is the result of println, which is Unit. Thus, getsFunct gets a thunk that evaluates only to Unit, so nothing is printed.

REPL Scenario 2: As Expected

0
source share

All Articles