Partially applied function doesn't work in Scala - scala

Why I can't invoke g2 with the second parameter in the line g2(1, _: Int)(9)?
g2(1, _: Int) returns a function <function1> and then I invoke that <function1> with parameter. At the same time in the example above I can invoke f3(9) however it is the same as g2(1, _: Int)(9) IMHO.
// OK
def f1: (Int, Int) => Int = _ + _
val f2: (Int, Int) => Int = f1
val f3: (Int) => Int = f2(1, _: Int)
println {
f3(9)
}
// FAIL
def g1: (Int, Int) => Int = _ + _
val g2: (Int, Int) => Int = g1
println {
g2(1, _: Int)(9) // Error: 'g2' does not take parameters
}

It's the issue with the scope of underscore in anonymous functions. See here for the rules: What are the rules to govern underscore to define anonymous function?
According to the rule 1 from the link above g2(1, _: Int)(9) is interpreted as (x: Int) => g2(1, x)(9). So you need to add parentheses, for the rule 2 to start working: (g2(1, _: Int))(9)

As you add in a comment, (g2(1, _: Int))(9) works.
Scala has multiple parameter lists, so f(x)(y) parses differently from (f(x))(y). As g takes only one parameter list, it can't take the second parameter list, hence the explicit grouping is necessary.
g2(1, _: Int)(9) means: take the function g2(x, y)(z), and apply parameters x = 1, z = 9.
(g2(1, _: Int))(9) means: take the function g2(x, y), and apply parameter x = 1. Then apply y = 9 to the resulting function.

Related

Scala : eta expansion of function values (not methods)

After experimenting with scala's eta expansion, I came across a weird feature.
Let's define a method:
scala> def sum(a: Int, b: Int): Int = a + b
sum: (a: Int, b: Int)Int
Ok, up until now, everything is fine. Now let's assign it to a val using eta expansion:
scala> val f = sum _
f: (Int, Int) => Int = $$Lambda$1051/694580932#55638165
Now, the strange thing is coming. I can apply eta expansion again to f, and it is working (however it adds currying to my method) :
scala> val g = f _
g: () => (Int, Int) => Int = $$Lambda$1055/1351568309#5602e540
Why is this working ? I thought that eta expansion was only valid for methods.
Moreover, I noticed that this is not possible:
scala> ((a: Int, b: Int) => a + b: Int) _
<console>:12: error: _ must follow method; cannot follow (Int, Int) => Int
((a: Int, b: Int) => a + b: Int) _
^
But is it not the same as applying eta expansion to f ?
I am a bit confused and these eta expansions still hide some magic for me.
Thanks a lot !
When you write val f = sum _ at the top level of the REPL or an object/class, Scala defines an accessor method so that you can access it. Here is how Scala desugars this (via scalac -Xprint:typer on val f: (Int, Int) => Int = _ + _):
private[this] val f: (Int, Int) => Int = ((x$1: Int, x$2: Int) => x$1.+(x$2));
<stable> <accessor> def f: (Int, Int) => Int = Foo.this.f;
So, when you subsequently write val g = f _, it's doing eta-expansion on the zero-argument accessor method, which results in the behavior you see. For more verification of this, notice that, if you put the definitions in a method, you get an error:
def foo = {
val f: (Int, Int) => Int = _ + _
val g = f _ // error: _ must follow method; cannot follow (Int, Int) => Int
}
This is because accessors are only generated for fields (and top-level REPL definitions, which are treated like fields).

Scala Syntax Partial

When I create a partial function, why can't I immediately invoke it?
Both res6 and res8 are the same type (function1) so I'm not sure how come res7 works (immediately invoking it) and what would be res9 fails
scala> ((x: Int) => x + 1)
res6: Int => Int = <function1>
scala> ((x: Int) => x + 1)(1)
res7: Int = 2
scala> def adder(a: Int, b: Int) = a + b
adder: (a: Int, b: Int)Int
scala> adder(1, _: Int)
res8: Int => Int = <function1>
scala> adder(1, _: Int)(1)
<console>:12: error: Int does not take parameters
adder(1, _: Int)(1)
^
scala> (adder(1, _: Int))(1)
res10: Int = 2
I think you've just found one of the little Scala compiler quirks.
I don't know how this case is implemented exactly in the parser, but from the looks of it Scala thinks you are invoking a function with multiple parameter lists (of the form f(...)(...)). Thus you need to explicitly surround the partially applied function with brackets here, so that compiler could disambiguate between f()() and f(_)() forms. In res8 you don't have any parameters following the function, so there is no ambiguity. Otherwise, Scala would require you to follow the function with underscore if you ommit parameter list: f _ or f() _.
You can still immediately apply that function as you show in res10.
adder(1, _: Int)
This is caused by scala compiler will expand it to:
((x: Int) => adder(1, x)(1))
and this is caused by the compiler can't infer the wildcard's context, like:
_ + _
scala> _ + _
<console>:17: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
_ + _
^
<console>:17: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
_ + _
so you can do it with context bounds, as your way:
(adder(1, _: Int))(1)
it will be expanded like:
((x: Int) => adder(1, x))(1)

scala : it is impossible to put a tuple as a function's argument

I can't pass a tuple as a method parameter:
scala> val c:Stream[(Int,Int,Int)]= Stream.iterate((1, 0, 1))((a:Int,b:Int,c:Int) => (b,c,a+b))
<console>:11: error: type mismatch;
found : (Int, Int, Int) => (Int, Int, Int)
required: ((Int, Int, Int)) => (Int, Int, Int)
thanks.
Just as the function literal:
(x:Int) => x + 1
is a function of one argument, the following
(x:Int, y: Int, z: Int) => x + y + z
is a function of three arguments, not one argument of a 3tuple
You can make this work neatly using a case statement:
scala> val c: Stream[(Int,Int,Int)] =
Stream.iterate((1, 0, 1)){ case (a, b, c) => (b, c, a+b) }
c: Stream[(Int, Int, Int)] = Stream((1,0,1), ?)
An alternative is to pass the tuple, but that's really ugly due to all the _1 accessors:
scala> val c:Stream[(Int,Int,Int)] =
Stream.iterate((1, 0, 1))( t => (t._2, t._3, t._1 + t._2) )
c: Stream[(Int, Int, Int)] = Stream((1,0,1), ?)
The lambda (a:Int,b:Int,c:Int) => (b,c,a+b) is a function taking three arguments. You want it to take one tuple, so you can write ((a:Int,b:Int,c:Int)) => (b,c,a+b). But this gives an error!
error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple3,
or consider a pattern matching anonymous function: `{ case (param1, ..., param3) => ... }
(((a:Int,b:Int,c:Int)) => (b,c,a+b))
^
Luckily, the error suggests a solution: { case (a, b, c) => (b, c, a+b) }
It is also possible to use the tupled option:
def a = (x:Int, y: Int, z: Int) => x + y + z).tupled
val sum = a((1,2,3))
My guess is that the expression (a:Int,b:Int,c:Int) => (b,c,a+b) defines a lambda with three arguments, and you need one decomposed argument.

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>

Scala - understanding a code snippet involving currying

I'm new to scala and I'm having a little trouble understanding currying - I'm practicing by coding simple functions for now, and would need clarification about the following
def mul (a: Int) (b: Int): Int =
{
{
a * b
}
}
Is the above function definition same as the below?
def mul: Int => Int => Int = {
(a: Int) =>
{
(b: Int) =>
a * b
}
}
From syntax I could interpret mul as a function that accepts an integer, and returns a function that accepts an integer and returns an integer. But I'm not sure if my interpretation is actually correct. Any explanation regarding the above example or the syntax of curried functions will be really helpful.
Your interpretation is correct. But you don't need all those braces.
def mul(a: Int)(b: Int) = a*b
val mulAB = (a: Int) => { (b: Int) => a*b } // Same as mul _
val mul5B = (b: Int) => 5*b // Same as mulAb(5) or mul(5) _
In general, you can rewrite any function with multiple arguments as a curried chain instead, where each argument produces a function that takes one fewer arguments until the last one actually produces the value:
f(a: A ,b: B ,c: C, d: D): E <===> A => B => C => D => E
In Scala, the natural grouping is by parameter block, not by individual parameter, so
f(a: A)(b: B, c: C)(d: D): E <===> A => (B,C) => D => E