I can understand this:
scala> def f(i: Int) = "dude: " + i
f: (i: Int)java.lang.String
scala> f(3)
res30: java.lang.String = dude: 3
It defines a function f that takes an int and returns a string that is of the form dude: + the int that is passed in.
Now the same function can be specified like this:
val f: Int => String = x => "dude: " + x
scala> f(3)
res31: String = dude: 3
Why do we need two =>
What does String = x mean? I thought that when you want to define something in Scala you'd do x:String?
You should parse it as
val (f: Int => String) = (x => "dude: " + x)
So it specifies that f has type (Int => String) and is defined as an anonymous function which takes an Int parameter (x) and returns a String.
Only to clarify a bit. def statements defines methods, not functions.
Now, for the function. You could have written it this way:
val f: (Int => String) = x => "dude: " + x
And it could be read as "f is a function from Int to String". So, answering your question, a => in a type position mean function from type to type, while => in a value position means takes parameter identifier and returns expression.
Further, it can also rely on the type inferrer:
val f = (x:Int) => "dude: " + x
Both Lee and pedrofurla gave excellent answers. I'll also add that if you want your method to be converted to a function (for passing as a parameter, use as a partially applied function, etc), you can use the magic underbar:
def foo(i: Int) = "dude: " + x
val bar = foo _ // now you have a function bar of type Int => String
Related
I'm looking at this sample code and after entering it in the scala repl I can see how it works.
val twice: Int => Int =
x => x * 2
This is similar:
val parse: String => Option[Int] =
s => if(s.matches("-?[0-9]+")) Some(s.toInt) else None
Can someone please deconstruct the above method and explain how this works?
I can see the name twice or parse, followed by the type which is Int => Int or String => Option[Int].
Now in the 2nd line of both functions you have a variable x or s. I can only assume this is the parameter.
Also if you can expand on what scala features allow a function to be written like this.
Thanks!
The expected type of value
x => x * 2
is
Int => Int
which de-sugars to
Function1[Int, Int]
hence function definition
val twice: Int => Int = x => x * 2
is equivalent to
val twice: Function1[Int, Int] = new Function1[Int, Int] {
override def apply(x: Int) = x * 2
}
as per SLS 6.3 Anonymous Functions.
When I define this function, I can call it without a problem:
scala> val c = (_: String) + "sd"
c: String => String = <function1>
scala> c("1")
res13: String = 1sd
However if I let the above function print the result without returning it, I have the following error:
scala> val b = print((_: String) + "sd")
<function1>b: Unit = ()
scala> b("1")
<console>:26: error: Unit does not take parameters
b("1")
^
I know the system method print returns Unit type, but shouldn't the function b be a function that can be called with an argument as I defined? Why the above b function can not be called with b("1")?
How to understand and solve the problem? Thank you.
Indeed, as you have already discovered
print((_: String) + "sd")
expands to
print((x: String) => x + "sd")
instead of the desired
(x: String) => print(x + "sd")
because _ binds to the innermost expression delimiter () or {}.
Consider the following sequence.
An anonymous function from String to String.
scala> (_: String) + "sd"
res0: String => String = $$Lambda$1156/0x00000008406c1040#6b8bdcc6
Print the String representation of the anonymous function.
scala> println((_: String) + "sd")
$line10.$read$$iw$$iw$$$Lambda$1158/0x00000008406c3040#31f5b923
Print the String representation of the anonymous function. Save the result in variable b.
scala> val b = println((_: String) + "sd")
$line11.$read$$iw$$iw$$$Lambda$1159/0x00000008406a7040#173cfb01
b: Unit = ()
The print() and println() passed parameter is call-by-reference, not call-by-name, so it is fully evaluated at the call site before being passed to print(). In this case print() receives a function, it doesn't become part of a larger function.
when defining method in Scala, I found this
def method1: Int => Int = (j: Int) => j // works
def method2: Int => Int = j => j // works
def method3: Int => Int = j: Int => j // error
def method4: Int => Int = {j: Int => j} // works
Can anyone explain why method3 does not work? Is there any ambiguity in it?
One possible explanation is indeed that this restriction avoids ambiguity: x: A => B could be understood as an anonymous function that takes a parameter x of type A and returns the object B. Or it could be understood as "casting" a variable x to the type A => B. It is very rare that both of these would be valid programs, but not impossible. Consider:
class Foo(val n: Int)
val Foo = new Foo(0)
val j: Int => Foo = new Foo(_)
def method1: Int => Foo = (j: Int) => Foo
def method2: Int => Foo = j: Int => Foo
println(method1(1).n)
println(method2(1).n)
This actually compiles and prints:
0
1
All of these variants are covered by Anonymous Functions section of the specification. The relevant part is
In the case of a single untyped formal parameter, (x) => e
can be abbreviated to
x => e. If an anonymous function (x : T) => e
with a single typed parameter appears as the result expression of a block, it can be abbreviated to
x: T => e.
In method3, the function isn't the result expression of a block; in method4 it is.
EDIT: oops, presumably you meant why the limitation is there. I'll leave this answer for now as stating what the limitation is exactly, and remove it if anyone gives a better answer.
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]
According to ScalaByExample:
A curried function definition def f (args1) ... (argsn) = E where n >
1 expands to
def f (args1) ... (argsn−1) = { def g (argsn) = E ; g }
Or, shorter, using an anonymous function:
def f (args1) ... (argsn−1) = ( argsn ) => E
Uncurried version:
def f(x: Int): Int => Int = {
y: Int => x * y
} //> f: (x: Int)Int => Int
def f1 = f(10) //> f1: => Int => Int
f1(5)
Curried version:
def g(x: Int)(y: Int) = {
x * y
} //> g: (x: Int)(y: Int)Int
def g1 = g(10) _ //> g1: => Int => Int
g1(5)
The question is, Why curried required the underscore in line #5 in the second code snippet.
You can find the explanation at Martin Odersky book: http://www.artima.com/pins1ed/functions-and-closures.html (search for "Why the trailing underscore").
In short this is because Scala is closer to Java in a lot of things, rather than functional languages where this is not required. This helps you to find out mistakes at compile time, if you forgot the missing argument.
If underscore was not required, the next code will compile:
println(g(10))
And this check helps you preventing such mistakes
There are some cases though, when such calls are obvious, and underscore is not required:
def g(x: Int)(y: Int) = {
x * y
}
def d(f: Int => Int) {
f(5)
}
d(g(10)) // No need to write d(g(2) _)
// Or any other way you can specify the correct type
val p: Int => Int = g(10)
Something to note: in Scala, def's are methods, not functions, at least, not directly. Methods are converted to functions by the compiler every time a method is used where a function would be required, but strictly speaking, a function would be created with val instead, like so:
val curry = (x: Int) => (y: Int) => x * y
This allows you to apply arguments one at a time without having to add a trailing underscore. It functions identically to the code in your first snippet, but because it uses val and not def, curry cannot be written like
val curry(x: Int) = (y: Int) => x * y //Won't compile
So, when you want to write a function that behaves the way you want a curried function to behave, write it like I did in my first snippet. You can keep chaining parameters with => as many times as you want (up to technical limits, but good luck hitting them).