I am new to Scala, and trying to understand the following codes (derived from an example in the Beginning Scala book)
scala> def w42(f: Int => Int) = f(42) //(A)
w42: (f: Int => Int)Int
scala> w42 (1 +) //(B)
res120: Int = 43
I do not understand how "1 +" at point (B) is consider as a function (take 1 Int parameter, and return an Int) that satisfies the w42 definition at point (A)?
Would you mind please explain or point me to some documents that have the answer?
Simple. In Scala 1 + 2 is just a syntax sugar over 1.+(2). This means Int has a method named + that accepts Int:
final class Int extends AnyVal {
def +(x: Int): Int = //...
//...
}
This is why you can use 1 + as if it was a function. Example with less unexpected method naming:
scala> def s42(f: String => String) = f("42")
s42: (f: String => String)String
scala> s42("abc".concat)
res0: String = abc42
BTW Technically speaking, eta-expansion is also involved to convert method to a function.
Related
I'm getting problems to understand the currying concept, or at least the SCALA currying notation.
wikipedia says that currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument.
Following this explanation, are the two next lines the same for scala?
def addCurr(a: String)(b: String): String = {a + " " + b}
def add(a:String): String => String = {b => a + " " + b}
I've run both lines with the same strings a and b getting the same result, but I don't know if they are different under the hood
My way of thinking about addCurr (and currying itself) is that it is a function that receives a string parameter a, and returns another function that also receives a string parameter b and returns the string a + " " + b?
So if I'm getting right, addCurr is only syntactic sugar of the function add and both are curryed functions?
According to the previous example, the next functions are also equivalent for scala?
def add(a: String)(b: String)(c: String):String = { a + " " + b + " " + c}
def add1(a: String)(b: String): String => String = {c => a + " " + b + " " + c}
def add2(a:String): (String => (String => String)) = {b => (c => a + " " + b + " " + c)}
They have a bit different semantics, but their use-cases are mostly the same, both practically and how it looks in the code.
Currying
Currying a function in Scala in that mathematical sense is a very straightforward:
val function = (x: Int, y: Int, z: Int) => 0
// function: (Int, Int, Int) => Int = <function3>
function.curried
// res0: Int => (Int => (Int => Int)) = <function1>
Functions & methods
You seem to be confused by the fact that in Scala, (=>) functions are not the same as (def) methods. Method isn't a first-class object, while function is (i.e. it has curried and tupled methods, and Function1 has even more goodness).
Methods, however, can be lifted to functions by an operation known as eta expansion. See this SO answer for some details. You can trigger it manually by writing methodName _, or it will be done implicitly if you give a method to where a function type is expected.
def sumAndAdd4(i: Int, j: Int) = i + j + 4
// sumAndAdd4.curried // <- won't compile
val asFunction = sumAndAdd4 _ // trigger eta expansion
// asFunction: (Int, Int) => Int = <function2>
val asFunction2: (Int, Int) => Int = sumAndAdd4
// asFunction2: (Int, Int) => Int = <function2>
val asFunction3 = sumAndAdd4: (Int, Int) => Int
// asFunction3: (Int, Int) => Int = <function2>
asFunction.curried
// res0: Int => (Int => Int) = <function1>
asFunction2.curried
// res1: Int => (Int => Int) = <function1>
asFunction3.curried
// res2: Int => (Int => Int) = <function1>
{sumAndAdd4 _}.tupled // you can do it inline too
// res3: Int => (Int => Int) = <function1>
Eta expansion of multiple parameter list
Like you might expect, eta expansion lifts every parameter list to its own function
def singleArgumentList(x: Int, y: Int) = x + y
def twoArgumentLists(x: Int)(y: Int) = x + y
singleArgumentList _ // (Int, Int) => Int
twoArgumentLists _ // Int => (Int => Int) - curried!
val testSubject = List(1, 2, 3)
testSubject.reduce(singleArgumentList) // Int (6)
testSubject.map(twoArgumentLists) // List[Int => Int]
// testSubject.map(singleArgumentList) // does not compile, map needs Int => A
// testSubject.reduce(twoArgumentLists) // does not compile, reduce needs (Int, Int) => Int
But it's not that currying in mathematical sense:
def hmm(i: Int, j: Int)(s: String, t: String) = s"$i, $j; $s - $t"
{hmm _} // (Int, Int) => (String, String) => String
Here, we get a function of two arguments, returning another function of two arguments.
And it's not that straightforward to specify only some of its argume
val function = hmm(5, 6) _ // <- still need that underscore!
Where as with functions, you get back a function without any fuss:
val alreadyFunction = (i: Int, j: Int) => (k: Int) => i + j + k
val f = alreadyFunction(4, 5) // Int => Int
Do which way you like it - Scala is fairly un-opinionated about many things. I prefer multiple parameter lists, personally, because more often than not I'll need to partially apply a function and then pass it somewhere, where the remaining parameters will be given, so I don't need to explicitly do eta-expansion, and I get to enjoy a terser syntax at method definition site.
Curried methods are syntactic sugar, you were right about this part. But this syntactic sugar is a bit different. Consider following example:
def addCur(a: String)(b: String): String = { a + b }
def add(a: String): String => String = { b => a + b }
val functionFirst: String => String = add("34")
val functionFirst2 = add("34")_
val functionSecond: String => String = add("34")
Generaly speaking curried methods allows for partial application and are necessary for the scala implicits mechanism to work. In the example above i provided examples of usage, as you can see in the second one we have to use underscore sign to allow compiler to do the "trick". If it was not present you would receive error similar to the following one:
Error:(75, 19) missing argument list for method curried in object XXX
Unapplied methods are only converted to functions when a function type
is expected. You can make this conversion explicit by writing curried_ or curried(_)(_) instead of curried.
Your question interested me so I tried this out my self. They actually desugar down to some very different constructs. Using
def addCurr(a: String)(b: String): String = {a + " " + b}
This actually compiles to
def addCurr(a: String, b: String): String = {a + " " + b}
So it completely removes any currying effect, making it a regular arity-2 method. Eta expansion is used to allow you to curry it.
def add(a:String): String => String = {b => a + " " + b}
This one works as you would expect, compiling to a method that returns a Function1[String,String]
I am new to scala. I have worked on java. defining of function in scala by using = operator does not make sense for me.
def abc(a:Int,b:Int):Int =
a+b
can anybody explain? in the above code, why i had to use = operator.
I believe there are many reasons. Just some of them:
1) uniform access:
val abc: Int = 5 //value
def abc: Int = 5 //factory
Note that such def abc can be implemented with val abc inside successor:
trait Interface {
def abc: Int //factory (reader)
}
object Implementation extends Interface {
val abc: Int = 5 //singleton
}
Some advanced examples: Why it's impossible to override `var` with `def` in Scala?
2) functions are just named lambda's:
val abc = (a: Int, b: Int) => a + b //lambda assigned to abc value
def abc (a:Int, b:Int): Int = a + b //abc method, that could be converted to lambda/function with eta-expansion: "abc _"
The syntactic difference between first and second one is just position of braces, so they are quite similar.
3) that function actually returns value, you might think of the a + b block independently from function definition, so then:
def abc ...: Int = {
val z = a + b
z
}
is almost like
val abc: Int = {
val z = a + b
z
}
But a and b are unknown, so we need to describe them too:
def abc(a: Int, b: Int): Int = {
val z = a + b
z
}
Otherwise, if your method doesn't return anything, you can omit = sign:
def abc(a: Int, b: Int) {
println(a + b)
}
Which is equivalent to:
def abc(a: Int, b: Int): Unit = {
println(a + b)
}
Where Unit (inhabited type with only one possible value, so it contains no information) roughly means that no value was returned.
See also official doc and language spec
This approach enhances the functional aspect of programming, where functions are no different than other data types.
e.g. In Scala
val number = 10
val function = (a:Int, b:Int) => a + b
Here, both the values number and function are immutable variables. Only difference is their types. number is of type Int, while function is of type (Int, Int) => Int
This enables functions to be treated just like Data and be passed around like other variables. This enhances into concepts like Higher Order Functions which can accept and return function values as opposed to literal values. As #dk14 mentioned, it's about uniform access.
There is one reason I know why scala uses = in method declaration is:
To return any value from method definition ,= has to be used or it cant return any value even if there is a return statement in method.
For Eg: look at below two code snippets:
def method1()
{
val a=1
return a
}
def method2()=
{
val a=1
return a
}
method1 return type is always unit even if it returns some values
whereas method2 returns value a .
I am trying to understand Partially applied function in scala
scala> val a=sum _
a: (Int, Int, Int) => Int = <function3>
scala> a(1,2,3)
res7: Int = 6
I am just giving this val a=sum _
I want to understand how scala interprets it will take 3 arguments
a: (Int, Int, Int) => Int = <function3>
You've just experienced the eta-expansion that is converting a method into a function.
Your method is sum which you are not demonstrating but based on the function version must be:
def sum(a:Int,b:Int,c:Int):Int = a + b + c
The underscore you are adding at the end is converting your method into a function as the descriptive type signature of the result shows: (Int, Int, Int) => Int
This way you are converting your method into a function value that can be assigned to a variable and passed around in your application logic conveying a behavioural change to your data (addition in your instance).
In the following code:
def product(f: Int => Int)(a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f)(a + 1, b)
The parameters a and b are passed to the inner function, but you could write exactly the same function definition like so:
def product(f: Int => Int, a:Int, b:Int): Int =
if (a > b) 1
else f(a) * product(f, a + 1, b)
So what is the purpose of separating the parameters? In other words, why do this:
(f: Int => Int)(a:Int, b:Int)
when you can more clearly write:
(f: Int => Int, a:Int, b:Int)
Another feature of multiple parameters lists is partial application:
def sum3(a: Int)(b: Int)(c: Int): Int = a + b + c
val g: Int => Int => Int = sum3(10) _
val h: Int => Int = g(20)
val r: Int = h(30) // 10 + 20 + 30 = 60
You can partially apply a function and obtain another function which is equivalent to the original one but with one of the arguments fixed. _ after sum3(10) is needed because sum3 is a method, not a function, and _ converts methods to functions.
This is very useful when you are using higher-order functions:
def adder(x: Int)(y: Int) = x + y
Seq(1, 2, 3, 4) map adder(10) // Seq(11, 12, 13, 14)
When partially applied method/function is used as an argument of a higher-order call, _ is not needed, and the syntax becomes very succinct.
Another use case of this feature is that if you want to create a control structure that looks like it's built into Scala programming language itself.
For example, I could write an control structure named times which help me execute the code block exactly n times by the following method definition:
// since block is call by name, it will not be evaluate when you call it.
def times(n: Int)(block: => Any): Unit = {
for (i <- 0 until n) {
block // evaluate(execute) block
}
}
// Now I can use the times method like a control structure
times(5) {
println("Hello World");
}
It depends whether there is implicit parameter (which can't be properly mixed with plain ones)...
def foo(i: Int)(implicit p: P): Foo
... and the way you want to call it ...
def foo1(a: Int)(b: Int => Boolean): Boolean
foo1(9) { i => false }
def foo2(a: Int, b: Int => Boolean): Boolean
foo2(9, { i => false })
def foo(x: Int, f: Unit => Int) = println(f())
foo(2, { Unit => 3 + 4 })
// case 1
def loop: Int = 7
foo(2, loop) // does not compile
changing loop to
// case 2
def loop(): Int = 7
foo(2, loop) // does not compile
changing loop to
// case 3
def loop(x: Unit): Int = 7 // changing according to Don's Comments
foo(2, loop) // compiles and works fine
Shouldn't case 1 and case 2 also work? Why are they not working?
Defining foo as
def foo(x: Int, y: () => Int)
then case 2 works but not case 1.
Arent they all supposed to work, defining the functions either way?
Also I think () => Int in foo is a bad style, y:=> Int does not work. Comments?
Scala distinguishes between the following things:
Functions/methods with no parameter lists ("by-name parameter" if a function)
Functions with one empty parameter list
Functions with one parameter of type Unit
None of these are equivalent, although as a convenience Scala allows you to elide empty parameter lists. (Incidentally, two empty parameter lists are also not the same.)
So, even though Unit is written (), this is not the same as the function argument parens () for a function or method. Instead, think of () as a Tuple0.
So, if you say f: Unit => Int, what you mean is "f takes one parameter, but it's a really boring parameter because it is Unit, which must always be the same boring Tuple0 value ()". What you're writing is really short for f: (Unit) => Int.
If you say f: () => Int, then you mean that "f takes no parameters and produces an Int".
If you say f: => Int, then you mean that "delay the execution of whatever statement produces an Int value until we use it in this code (and re-evaluate it each time)". Functionally, this ends up being basically the same as f: () => Int (and internally is converted into the same Function0 class), but it has a different usage, presumably to allow for a more compact form of closures (you always omit the => in the calling code).
()=>Int is Function0[Int] while Unit=>Int is Function1[Unit,Int]
scala> val function0: () => Int = () => 5
function0: () => Int = <function0>
scala> val function1: Unit => Int = u => 5
function1: (Unit) => Int = <function1>
scala> function0()
res0: Int = 5
scala> function1("anything")
res1: Int = 5
scala> function1(100)
res2: Int = 5
scala>
Also note that () is an object of Unit
scala> function1(())
res11: Int = 5
scala> function1 ()
res12: Int = 5
scala> function1()
res13: Int = 5
scala> val unit = ()
unit: Unit = ()
scala> function1(unit)
res15: Int = 5
scala> function1 apply unit
res16: Int = 5
scala>
In case 1 and 2 above, the return value of loop rather than loop itself is type checked for the second argument to foo and fails: Int != Unit => Int
The change to loop has a typo.