Scala method created using function literals - scala

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

Related

difference between following def and val partial functions

Is there a difference between whether I use def or val while defining a partial function? I thought that probably def will be evaluated everytime (like a function call) while val will be evaluated only once but that doesn't seem to be the case.
scala> def add(x:Int)(y:Int) = {println("inadd");x+y}
add: (x: Int)(y: Int)Int
//def
scala> def add2ToDef= add(2) _
add2ToDef: Int => Int
//val
scala> val add2ToVal= add(2) _
add2ToVal: Int => Int = $$Lambda$1032/1413020227#512abf25
scala> add2ToDef(3)
inadd
res0: Int = 5
scala> add2ToVal(3)
inadd
res1: Int = 5
scala> add2ToDef(4)
inadd
res2: Int = 6
scala> add2ToVal(5)
inadd
res3: Int = 7
Essentially the same difference as between val and def in general:
def will produce a new lambda (new object) every time you reference it.
val will produce it once (at definition time) and every reference to it refers to the same instance.
In this case, val makes more sense so it's not creating a new lambda every time.
You are right that:
def will be evaluated every time you reference the function and val will be evaluated only once and the same value will be used every time.
It is true with partial functions as well. To see the behavior you can see this example:
scala> def add(x:Int)(y:Int) = {println("inadd");x+y}
add: (x: Int)(y: Int)Int
scala> def addWithDef = add(2)(3)
addWithDef: Int
scala> addWithDef // Evaluated
inadd
res0: Int = 5
scala> addWithDef // Evaluated again as "inadd" is printed again
inadd
res1: Int = 5
scala> val addWithVal = add(2)(3) // Evaluated once
inadd
addWithVal: Int = 5
scala> addWithVal //Same value referenced again(no "inadd" printed)
res2: Int = 5
scala> addWithVal //Same value referenced again(no "inadd" printed)
res3: Int = 5

Underscore after function?

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

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

Scala, Currying on multi parameter-group method?

I am wondering if it is possible to use currying on multi parameter-group functions :
scala> def sum(a: Int)(b: Int): Int = { a+b }
sum: (a: Int)(b: Int)Int
scala> sum(3)(4)
res2: Int = 7
scala> val partFunc = sum(3) _
partFunc: Int => Int = <function1>
scala> partFunc(4)
res3: Int = 7
scala> val partFunc2 = sum _ _
<console>:1: error: ';' expected but '_' found.
val partFunc2 = sum _ _
^
scala> val partFunc2 = (sum _) _
<console>:8: error: _ must follow method; cannot follow Int => (Int => Int)
val partFunc2 = (sum _) _
Writing simply sum _ does not yet have anything to do with the arguments of sum, but simply distinguishes the function object sum from an application of the function.
Hence, you can write:
scala> val partFunc2 = sum _
partFunc2: Int => (Int => Int) = <function1>
As you can see from the type information, this is already the curried version of sum which takes two Int parameters.
Of course, you can then proceed as before with partFunc2(4) being of type Int => Int and so on.
You can do it like this:
val partFunc2 = sum _
or like this:
val partFunc2 = sum(3) _

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)