Underscore after function? - scala

Given
scala> def method(x: Int) = x
method: (x: Int)Int
scala> val func = (x: Int) => x
func: Int => Int = <function1>
Consider the following code:
scala> method _
res0: Int => Int = <function1>
scala> func(_)
res1: Int => Int = <function1>
scala> func _
res2: () => Int => Int = <function0>
I can understand that res0 is eta expansion and res1 is equivalent to lambda function (x) => func(x). But I cannot figure out the output of res2. Could anyone please explain that for me?

This is actually a bit tricky. First, let's see what happens outside REPL:
It doesn't work when func is a local variable:
object Main extends App {
def foo() = {
val f = (_: Int) + 1
f _
}
println(foo())
}
[error] /tmp/rendereraEZGWf9f1Q/src/main/scala/test.scala:8: _ must follow method; cannot follow Int => Int
[error] f _
[error] ^
But if you put it outside def foo, it compiles:
object Main extends App {
val f = (_: Int) + 1
val f1 = f _
println(f1)
}
because f is both a field of Main and a method without arguments which returns the value of this field.
The final piece is that REPL wraps each line into an object (because Scala doesn't allow code to appear outside a trait/class/object), so
scala> val func = (x: Int) => x
func: Int => Int = <function1>
is really something like
object Line1 {
val func = (x: Int) => x
}
import Line1._
// print result
So func on the next line refers to Line1.func which is a method and so can be eta-expanded.

You've used the eta Expansion to turn res2 into a function that takes 0 parameters and returns a function that takes a single parameter.
res2: () => Int => Int = <function0>
So you can now do this:
val zero = func _
val f: Int => Int = zero()

To answer your question about res2 - the appended underscore _ syntax is used to partially apply a function.
So.
scala> func _
Means you have partially applied your <function1>.
This results in a new curried form, the first function of which takes zero arguments (hence <function0>)
() =>
Which returns your original <function1> which takes 1 argument.
Int => Int = <function1>
The complete result being the chain of functions.
res2: () => Int => Int = <function0>
The rule that might be useful for you to remember is that functions associate to the right so the following are equivalent.
() => Int => Int
() => (Int => Int)
This other post might be useful reading for you.

val func1 = func _
This returns a function0 which takes no arguments and returns the func function.
You can use this like:
func1()(2) // outputs 2
You can continue doing this kind of expansion ad infinitum:
val func2 = func1 _
func2()()(2) // outputs 2

Related

Scala method created using function literals

I am new to scala and was playing around with few concepts but got stuck with following one.
If i create a method like
def sample(value:Int) = {(x:Int)=>x+1}
This works in Scala and can be tested as sample(100), but I am not able to understand as how a method and literal here can be clubbed. Can someone explain what exactly is happening?
The parameter value here is never used and is therefore redundant. The method sample() returns a function which takes one integer parameter (which is discarded) and then adds 1 to it. So you get:
scala> def sample(value:Int) = { (x:Int) => x + 1 }
sample: (value: Int)Int => Int
scala> sample(100)
res2: Int => Int = <function1>
scala> sample(100)(10)
res3: Int = 11
scala> val f = sample(99)
f: Int => Int = <function1>
scala> f(1)
res4: Int = 2
You could use the value parameter in the following way:
scala> def plusX(value:Int) = { (x:Int) => x + value}
plusX: (value: Int)Int => Int
scala> val plus10 = plusX(10)
plus10: Int => Int = <function1>
scala> plus10(15)
res7: Int = 25
Now plusX creates a function which takes a integer and adds the value value to it

anonymous function with multiple parameter lists

I am trying to declare a simple method in scala with multiple parameter lists.
These two work.
scala> def add(a:Int, b:Int) = a+ b
add: (a: Int, b: Int)Int
scala> def add(a:Int)(b:Int) = a + b
add: (a: Int)(b: Int)Int
This does not...
scala> val add = (a:Int)(b:Int)=>a + b
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple1,
or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val add = (a:Int)(b:Int)=>a + b
But why ... all I am trying to do is to assign a anonymous function which takes multiple parameter lists to a value. that works with a single parameter list but not with multiple parameter lists.
It's just a matter of syntax when declaring the curried arguments.
scala> val add = (a:Int) => (b:Int) => a + b
add: Int => (Int => Int) = <function1>
scala> add(4)
res5: Int => Int = <function1>
scala> res5(9)
res6: Int = 13
Example of anonymous usage:
scala> def doit(f: Int => Int => String): String = f(2)(5)
doit: (f: Int => (Int => String))String
scala> doit(a => b => (a+b).toString)
res8: String = 7

Obtain reference to arity-0 scala function

Scala allows functions with no parameter lists to be invoked without parentheses:
scala> def theAnswer() = 42
theAnswer: ()Int
scala> theAnswer
res5: Int = 42
How would I construct a scala expression that evaluates to the function theAnswer itself, rather than the result of theAnswer? Or in other words, how would I modify the expression theAnswer, so that the result was of type () => Int, and not type Int?
It can be done with:
scala> theAnswer _
res0: () => Int = <function0>
From the answer to the similar question:
The rule is actually simple: you have to write the _ whenever the
compiler is not explicitly expecting a Function object.
This call will create the new instance every time, because you're "converting" method to function (what is called "ETA expansion").
Simply:
scala> val f = () => theAnswer
f: () => Int = <function0>
scala> val g = theAnswer _
g: () => Int = <function0>

Curried function in scala

I have a definition of next methods:
def add1(x: Int, y: Int) = x + y
def add2(x: Int)(y: Int) = x + y
the second one is curried version of first one. Then if I want to partially apply second function I have to write val res2 = add2(2) _. Everything is fine. Next I want add1 function to be curried. I write
val curriedAdd = (add1 _).curried
Am I right that curriedAdd is similiar to add2?
But when I try to partially apply curriedAdd in a such way val resCurried = curriedAdd(4) _ I get a compilation error. Then I fix it to
val resCurried = curriedAdd(4)
Why the result of a Functions.curried differs from curried version of add function(from add2)?
Firstly curriedAdd is same as add2 _ and not add2. add2 is just a method.
scala> curriedAdd
res52: Int => (Int => Int) = <function1>
scala> add2 _
res53: Int => (Int => Int) = <function1>
About the second question. I think the below is the reason. Doing
scala> val i = curriedAdd(23)
i: Int => Int = <function1>
scala> i _
res54: () => Int => Int = <function0>
scala> curriedAdd(23) _
<console>:10: error: _ must follow method; cannot follow Int => Int
curriedAdd(23) _
curriedAdd(23) _ does not work. Lets look at scala manual (§6.7)-
The expression e _ is well-formed if e is of method type or if e is a
call-by-name parameter. If e is a method with parameters, e _
represents e converted to a function type by eta expansion (§6.26.5).
If e is a parameterless method or call-by-name parameter of type =>T ,
e _ represents the function of type () => T , which evaluates e when
it is applied to the empty parameterlist ().
Remember it only evaluates if it is a method or call-by-name parameter. In curriedAdd(23) _, it does not evaluate curriedAdd(23) but checks if it is a method or call-by-name. It is not a method nor a call-by-name parameter.
It is not by-name because by-name is the property of variable. Above you get a by-name parameter after evaluating curriedAdd(23) but curriedAdd(23) in itself is not a by-name variable. Hence the error (Ideally the compiler should have coverted it). Note that the below works:
scala> curriedAdd(23)
res80: Int => Int = <function1>
scala> res80 _
res81: () => Int => Int = <function0>
The above works because res80 _, here you are applying _ to a call-by-name parameter and hence does the conversion.
To answer this question, let's take a look at the REPL.
First we define the two functions as you did.
scala> def add1(x: Int, y: Int) = x + y
add1: (x: Int, y: Int)Int
scala> def add2(x: Int)(y: Int) = x + y
add2: (x: Int)(y: Int)Int
We have defined two functions. The first one expects two parameters in one parameterlist. The second one expects two parameters, each one in an own parameterlist. The result type is the same.
Let's move on.
scala> val curriedAdd = (add1 _).curried
curriedAdd: Int => (Int => Int) = <function1>
You just created a partial applied function, that expects one parameter and returns a partial applied function of type Int => Int. This is not as similar to add2 as you expect it to be.
To achieve the same for add2, you would need to call
scala> val curriedAdd2 = add2 _
curriedAdd2: Int => (Int => Int) = <function1>

Force accessing of a def

Considering
object A {
def m(i: Int) = i
val m = (i: Int) => i * 2
}
one gets
scala> A.m(2)
<console>: error: ambiguous reference to overloaded definition,
both value m in object A of type => (Int) => Int
and method m in object A of type (i: Int)Int
match argument types (Int)
A.m(2)
^
Accessing the val can be done with
scala> val fun = A.m
fun: (Int) => Int = <function1>
scala> fun(2)
res: Int = 4
or
scala> A.m.apply(2)
res: Int = 4
but how would one access the def?
It is total rubbish (please, don't do this at home), but you can do it by assigning A to a variable of structural type, that has only the first m.
val x : { def m(i:Int):Int } = A
x.m(10)