What is the difference between:
def even: Int => Boolean = _ % 2 == 0
and
val even: Int => Boolean = _ % 2 == 0
Both can be called like even(10).
Method def even evaluates on call and creates new function every time (new instance of Function1).
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
With def you can get new function on every call:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val evaluates when defined, def - when called:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
Note that there is a third option: lazy val.
It evaluates when called the first time:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
But returns the same result (in this case same instance of FunctionN) every time:
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
Performance
val evaluates when defined.
def evaluates on every call, so performance could be worse than val for multiple calls. You'll get the same performance with a single call. And with no calls you'll get no overhead from def, so you can define it even if you will not use it in some branches.
With a lazy val you'll get a lazy evaluation: you can define it even if you will not use it in some branches, and it evaluates once or never, but you'll get a little overhead from double check locking on every access to your lazy val.
As #SargeBorsch noted you could define method, and this is the fastest option:
def even(i: Int): Boolean = i % 2 == 0
But if you need a function (not method) for function composition or for higher order functions (like filter(even)) compiler will generate a function from your method every time you are using it as function, so performance could be slightly worse than with val.
Consider this:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
Do you see the difference? In short:
def: For every call to even, it calls the body of the even method again. But with even2 i.e. val, the function is initialized only once while declaration (and hence it prints val at line 4 and never again) and the same output is used each time it accessed. For example try doing this:
scala> import scala.util.Random
import scala.util.Random
scala> val x = { Random.nextInt }
x: Int = -1307706866
scala> x
res0: Int = -1307706866
scala> x
res1: Int = -1307706866
When x is initialized, the value returned by Random.nextInt is set as the final value of x. Next time x is used again, it will always return the same value.
You can also lazily initialize x. i.e. first time it is used it is initialized and not while declaration. For example:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
See this:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
Surprisingly, this will print 4 and not 9! val (even var) is evaluated immediately and assigned.
Now change val to def.. it will print 9! Def is a function call.. it will evaluate each time it is called.
val i.e. "sq" is by Scala definition is fixed. It is evaluated right at the time of declaration, you can't change later. In other examples, where even2 also val, but it declared with function signature i.e. "(Int => Boolean)", so it is not Int type. It is a function and it's value is set by following expression
{
println("val");
(x => x % 2 == 0)
}
As per Scala val property, you can't assign another function to even2, same rule as sq.
About why calling eval2 val function not printing "val" again and again ?
Orig code:
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
We know, in Scala last statement of above kind of expression (inside { .. }) is actually return to the left hand side. So you end up setting even2 to "x => x % 2 == 0" function, which matches with the type you declared for even2 val type i.e. (Int => Boolean), so compiler is happy. Now even2 only points to "(x => x % 2 == 0)" function (not any other statement before i.e. println("val") etc. Invoking event2 with different parameters will actually invoke "(x => x % 2 == 0)" code, as only that is saved with event2.
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
Just to clarify this more, following is different version of the code.
scala> val even2: (Int => Boolean) = {
| println("val");
| (x => {
| println("inside final fn")
| x % 2 == 0
| })
| }
What will happen ? here we see "inside final fn" printed again and again, when you call even2().
scala> even2(3)
inside final fn
res9: Boolean = false
scala> even2(2)
inside final fn
res10: Boolean = true
scala>
Executing a definition such as def x = e will not evaluate the expression e. In- stead e is evaluated whenever x is invoked.
Alternatively, Scala offers a value definition
val x = e,which does evaluate the right-hand-side as part of the evaluation of the definition.
If x is then used subsequently, it is immediately replaced by the pre-computed value of e, so that the expression need not be evaluated again.
also, Val is a by value evaluation. Which means the right-hand side expression is evaluated during definition. Where Def is by name evaluation. It will not evaluate until it's used.
In addition to the above helpful replies, my findings are:
def test1: Int => Int = {
x => x
}
--test1: test1[] => Int => Int
def test2(): Int => Int = {
x => x+1
}
--test2: test2[]() => Int => Int
def test3(): Int = 4
--test3: test3[]() => Int
The above shows that “def” is a method (with zero argument parameters) that returns another function "Int => Int” when invoked.
The conversion of methods to functions is well explained here: https://tpolecat.github.io/2014/06/09/methods-functions.html
In REPL,
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292#57a0aeb8
def means call-by-name, evaluated on demand
val means call-by-value, evaluated while initialization
Note: There are different types of functions in Scala: abstract, concrete, anonymous, high order, pure, impure etc...
Explaining val function:
A val function in Scala is a complete object. There are traits in Scala to represent functions with various numbers of arguments: Function0, Function1, Function2, etc. As an instance of a class that implements one of these traits, a function object has methods. One of these methods is the apply method, which contains the code that implements the body of the function.
When we create a variable whose value is a function object and we then reference that variable followed by parentheses, that gets converted into a call to the apply method of the function object.
Explaining Method i.e def:
Methods in Scala are not values, but functions are.
A Scala method, as in Java, is a part of a class. It has a name, a signature, optionally some annotations, and some bytecode.
The implementation of a method is an ordered sequence of statements that produces a value that must be compatible with its return type.
Related
In following code:
scala> val double = (i: Int) => {
| println("I am here")
| i * 2
| }
double: Int => Int = $$Lambda$1090/773348080#6ae9b2f0
scala> double(4)
I am here
res22: Int = 8
scala> val evenFunc: (Int => Boolean) = {
| println("I am here");
| (x => x % 2 == 0)
| }
I am here
evenFunc: Int => Boolean = $$Lambda$1091/373581540#a7c489a
scala> double
res23: Int => Int = $$Lambda$1090/773348080#6ae9b2f0
scala> evenFunc
res24: Int => Boolean = $$Lambda$1091/373581540#a7c489a
scala> evenFunc(10)
res25: Boolean = true
scala> def incr(x:Int) = x+1
incr: (x: Int)Int
scala> incr
<console>:13: error: missing argument list for method incr
Unapplied methods are only converted to functions when a function type is
expected.
You can make this conversion explicit by writing `incr _` or `incr(_)`
instead of `incr`.
incr
double and evenFunc are function variables and we have assigned function literals to them.But as output shows, when we call double, println statement is also executed.But evenFunc doesn't execute println statement, except when defined. incr is defined with keyword def, so its behaviour is as expected.
Why do double and evenFunc behave differently, even though both refer to function literals?
The point at which the input parameter is received is the pivot.
If you change evenFunc from...
println("I am here")
x => x % 2 == 0
... to ...
x =>
println("I am here")
x % 2 == 0
...you'll get the same behavior as observed with double.
What comes before the received argument is evaluated/executed where the function is defined. What comes after the received argument is executed each time the function is invoked.
The difference is rather clear
(i: Int) => {
println("I am here")
i * 2
}
{
println("I am here");
(x => x % 2 == 0)
}
The function literal is defined as (param list) => body. Hence, the println statement in the 2nd is evaluated before and beyond the the function literal so that it's not part of the function body.
I want to understand the difference between the closure declared as val and the one declared as method (with the def kyeword). What's exactly the difference between theses two functions, is the ep method a closure ?
scala > var more=10
scala > val phi= (x:Int)=>x+more
scala > def ep(x:Int):Int= x+more
A function object that captures free variables, and is said to be
“closed” over the variables visible at the time it is created is called closure. For example:
var foo = 10
val bar = (x:Int) => x+foo
Here, foo is free variable in function literal and hence the function literal is open term. As a result, val bar is a closure since function value (object) is created with open term foo.
Now, lets start with different between val and def in term of function definition.
In scala, function is a value and you can assign it to variable.
When you define a function with val, you are defining it with a function literal as val bar = (x:Int) => x+foo, which return a function object and assign it as value to bar. In case of val, the function value is evaluated as it is defined. That means, function literal (x:Int) => x+foo is evaluated to function value with free variable foo and is stored in bar variable as closure.
//In the following snippet, a function literal is evaluated to object Function1 and assigned to val bar.
scala> var foo = 10
foo: Int = 10
scala> val bar = (x: Int) => x + foo
bar: Int => Int = <function1> //Function1 object is returned
Since, bar is a value and is evaluated as it is defined, it will always refer to same object in the memory whenever accessed.
scala> bar eq bar //because both instance refer to same instance.
res11: Boolean = true
On the other hand, you define a method with def and method is not a function in Scala. According to Scala language specification, method do not have type in Scala hence it cannot be used as value.
For example, you cannot do as:
val bar = {def foo(x:Int): Int = x + 1 }
However, according to Specification, if method name is used as value, then Scala implicitly converts it to corresponding function type with ETA Expression. e.g. method def a: Int is converted as a: => Int. That means, every time you call method, it returns a function value.
scala> def foo():Int = 1
a: ()Int
scala> val bar:( ()=> Int) = foo
bar: () => Int = <function0> //foo return Function0
//Note, val bar = foo, will assign the value returned by foo instead of returning function, so specify type.
Because of this, method can be used as function. For example, when ever some method or function require a function type as argument, you can provide def method.
scala> val foo = (x:Int, double:Function1[Int, Int]) => double(x)
foo: (Int, Int => Int) => Int = <function2>
scala> def double(x:Int):Int = x * 2
double: (x: Int)Int
scala> foo(3, double)
res1: Int = 6
In addition, note that with method, you get a new function on every call.
scala> def double: Int => Int = _ * 2
double: Int => Int
scala> double eq double
res15: Boolean = false //false because every time double refers to new instance and hence is not equal unlike val.
Now, lets go to closure.
Both function literal defined with val and def method return function value (object). The function value (the object) that’s created at runtime from function literal is closure. On the other hand, a method is not a closure, but the function value you get from calling a method is a closure.
scala> var more = 1
more: Int = 1
scala> val foo = (x:Int) => x + more // foo is clouser.
foo: Int => Int = <function1>
scala> def bar(x:Int):Int = x + more // bar is not clouser.
bar: (x: Int)Int
scala> val barClouser : (Int => Int) = bar // barClouser is clouser.
barClouser: Int => Int = <function1>
scala> val barValue = bar(3) // bar is converted to clouser and then clouser value is evaluated and result is assigned to barValue variable.
barValue: Int = 4
scala> val fooValue = foo(3) //foo value is evaluated and returned as value which is assigned to fooValue variable.
fooValue: Int = 4
What is the difference between:
def even: Int => Boolean = _ % 2 == 0
and
val even: Int => Boolean = _ % 2 == 0
Both can be called like even(10).
Method def even evaluates on call and creates new function every time (new instance of Function1).
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
With def you can get new function on every call:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val evaluates when defined, def - when called:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
Note that there is a third option: lazy val.
It evaluates when called the first time:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
But returns the same result (in this case same instance of FunctionN) every time:
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
Performance
val evaluates when defined.
def evaluates on every call, so performance could be worse than val for multiple calls. You'll get the same performance with a single call. And with no calls you'll get no overhead from def, so you can define it even if you will not use it in some branches.
With a lazy val you'll get a lazy evaluation: you can define it even if you will not use it in some branches, and it evaluates once or never, but you'll get a little overhead from double check locking on every access to your lazy val.
As #SargeBorsch noted you could define method, and this is the fastest option:
def even(i: Int): Boolean = i % 2 == 0
But if you need a function (not method) for function composition or for higher order functions (like filter(even)) compiler will generate a function from your method every time you are using it as function, so performance could be slightly worse than with val.
Consider this:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
Do you see the difference? In short:
def: For every call to even, it calls the body of the even method again. But with even2 i.e. val, the function is initialized only once while declaration (and hence it prints val at line 4 and never again) and the same output is used each time it accessed. For example try doing this:
scala> import scala.util.Random
import scala.util.Random
scala> val x = { Random.nextInt }
x: Int = -1307706866
scala> x
res0: Int = -1307706866
scala> x
res1: Int = -1307706866
When x is initialized, the value returned by Random.nextInt is set as the final value of x. Next time x is used again, it will always return the same value.
You can also lazily initialize x. i.e. first time it is used it is initialized and not while declaration. For example:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
See this:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
Surprisingly, this will print 4 and not 9! val (even var) is evaluated immediately and assigned.
Now change val to def.. it will print 9! Def is a function call.. it will evaluate each time it is called.
val i.e. "sq" is by Scala definition is fixed. It is evaluated right at the time of declaration, you can't change later. In other examples, where even2 also val, but it declared with function signature i.e. "(Int => Boolean)", so it is not Int type. It is a function and it's value is set by following expression
{
println("val");
(x => x % 2 == 0)
}
As per Scala val property, you can't assign another function to even2, same rule as sq.
About why calling eval2 val function not printing "val" again and again ?
Orig code:
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
We know, in Scala last statement of above kind of expression (inside { .. }) is actually return to the left hand side. So you end up setting even2 to "x => x % 2 == 0" function, which matches with the type you declared for even2 val type i.e. (Int => Boolean), so compiler is happy. Now even2 only points to "(x => x % 2 == 0)" function (not any other statement before i.e. println("val") etc. Invoking event2 with different parameters will actually invoke "(x => x % 2 == 0)" code, as only that is saved with event2.
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
Just to clarify this more, following is different version of the code.
scala> val even2: (Int => Boolean) = {
| println("val");
| (x => {
| println("inside final fn")
| x % 2 == 0
| })
| }
What will happen ? here we see "inside final fn" printed again and again, when you call even2().
scala> even2(3)
inside final fn
res9: Boolean = false
scala> even2(2)
inside final fn
res10: Boolean = true
scala>
Executing a definition such as def x = e will not evaluate the expression e. In- stead e is evaluated whenever x is invoked.
Alternatively, Scala offers a value definition
val x = e,which does evaluate the right-hand-side as part of the evaluation of the definition.
If x is then used subsequently, it is immediately replaced by the pre-computed value of e, so that the expression need not be evaluated again.
also, Val is a by value evaluation. Which means the right-hand side expression is evaluated during definition. Where Def is by name evaluation. It will not evaluate until it's used.
In addition to the above helpful replies, my findings are:
def test1: Int => Int = {
x => x
}
--test1: test1[] => Int => Int
def test2(): Int => Int = {
x => x+1
}
--test2: test2[]() => Int => Int
def test3(): Int = 4
--test3: test3[]() => Int
The above shows that “def” is a method (with zero argument parameters) that returns another function "Int => Int” when invoked.
The conversion of methods to functions is well explained here: https://tpolecat.github.io/2014/06/09/methods-functions.html
In REPL,
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292#57a0aeb8
def means call-by-name, evaluated on demand
val means call-by-value, evaluated while initialization
Note: There are different types of functions in Scala: abstract, concrete, anonymous, high order, pure, impure etc...
Explaining val function:
A val function in Scala is a complete object. There are traits in Scala to represent functions with various numbers of arguments: Function0, Function1, Function2, etc. As an instance of a class that implements one of these traits, a function object has methods. One of these methods is the apply method, which contains the code that implements the body of the function.
When we create a variable whose value is a function object and we then reference that variable followed by parentheses, that gets converted into a call to the apply method of the function object.
Explaining Method i.e def:
Methods in Scala are not values, but functions are.
A Scala method, as in Java, is a part of a class. It has a name, a signature, optionally some annotations, and some bytecode.
The implementation of a method is an ordered sequence of statements that produces a value that must be compatible with its return type.
I am trying to learn scala and understand difference between functions and methods.
Here is very simple code I wrote -
scala> class C ( acc:Int) {
| val minc = ( acc + 1 )
| val func = { () => acc += 3 }
| }
scala> val c1 = new C(3)
c1: C = C#55e610e3
scala> c1.minc
res2: Int = 4
scala> c1.func
res3: () => Int = <function0>
I understand that result of calling function func on instantiated object c1 is stored as another expression res3.
However I want to get value out of of anonymous function () = acc +3 that is inside class C.
If I try to pass argument to res3 expression scala throws an error
scala> res3(4)
<console>:11: error: too many arguments for method apply: ()Int in trait Function0
res3(4)
^
How to get value out of it ?
PS - I have just started with scala and don't know if this is at all possible or not ?
This is your definition of func:
val func = { () => acc += 3 }
Let's take a look in the REPL at what is the type of func.
scala> val c1 = new C(3)
val c1 = new C(3)
c1: C = C#58db88e9
scala> c1.func
c1.func
res29: () => Unit = <function0>
In plain English, this means "func refers to a function that accepts no arguments and doesn't return a value." Unit means the method doesn't return anything. If you're coming from Java, then it's analogous to void as the return type. function0 means it accepts 0 arguments.
Next, let's take a look at the failing call in your example.
scala> c1.func(4)
c1.func(4)
<console>:10: error: too many arguments for method apply: ()Unit in trait Function0
c1.func(4)
^
Now that we know the method signature of func, this error message should make more sense. We know that func refers to a function that accepts no arguments, yet in this call, you have attempted to call it with a single integer argument. Since the method call has too many arguments, Scala correctly reports this as an error.
I am not entirely sure what you were trying to do by passing 4 as an argument. My best guess is that you are trying to apply the function to calculate its result by adding 3 to acc and then returning it to the caller. If I'm right, then we can redefine C as this:
class C(var acc:Int) {
val minc = ( acc + 1 )
val func = () => {
acc += 3
acc
}
scala> val c1 = new C(3)
val c1 = new C(3)
c1: C = C#58db88e9
scala> c1.func()
c1.func()
res44: Int = 6
When we call c1.func(), no arguments are passed, so it correctly matches the defined method signature.
Another possibility is that you were trying to parameterize the increment amount and pass 4 to it in the call. If so, then you can do this:
class C(var acc:Int) {
val minc = ( acc + 1 )
val func = (delta: Int) => {
acc += delta
acc
}
}
scala> c1.func(4)
c1.func(4)
res45: Int = 7
In this case, we have declared that the anonymous function accepts 1 argument of type Int, so when we pass 4 in the method call, it correctly matches the method signature.
You're not declaring an anonymous function in the way you think. This line:
val func = { () => acc += 3 }
That actually declares 2 anonymous functions. The brackets are the first anonymous function (that takes no arguments), and the () => acc += 3 is the second function. Scala allows you to declare a 0-arity anonymous function by just using brackets. If you drop those, you'll have what you want:
val func = () => acc += 3
As a bit of a side note, you can see this in the type signature. Your current signature for func is:
() => Int = <function0>
That's a function that takes 0 arguments and returns an integer. That's not what you want. When you change it to what I gave you, you'll get this:
Int => Int = <function1>
Now func takes a single argument, and Integer, and returns another Integer, which is what you wanted.
What's the verbose way for val Singleton4 : Set = set => set == 4? I am unable to understand where the set parameter is coming from.
What maybe confuses you is the fact that Set is not what one would expect from the Scala library. You should read the line as:
val Singleton4: Int => Boolean = someArbitraryName => someArbitraryName == 4
// <identifier> <type> = <argument> => <returnValue>
It's not "coming" from anywhere, Set is defined as a function from an integer to a boolean and the type of Singleton4 is exactly that, it takes an integer and returns a function which needs another integer and returns a boolean:
scala> type Set = Int => Boolean
defined type alias Set
scala> def singletonSet(elem: Int): Set = set => set == elem
singletonSet: (elem: Int)Int => Boolean
scala> val p: Set = singletonSet(3)
p: Int => Boolean = <function1>
So now p is a function which takes an integer:
scala> p(3)
res0: Boolean = true
scala> p(2)
res1: Boolean = false
An alternative way of writing that is this:
def singletonSet(elem: Int) = (i: Int) => i == elem
val p: (Int) => Boolean = singletonSet(3)
Or using a different way but achieving the same result:
def singletonSet(elem: Int)(i: Int): Boolean = i == elem
val p: (Int) => Boolean = singletonSet2(3)
By currying the function and applying only one argument you get back a function which still needs another integer to be fully evaluated.
The other answers are very good, but I thought I'd throw some additional details to help newcomers to Scala understand the notation better (as there are some hidden gems in the notation that were not uncovered/described).
Let's play the Scala compiler game!
The following val says enough about what Set the type represents.
val Singleton4: Set = set => set == 4
The type of val is given explicitly - it's Set. We don't however know much about it...yet. It has however to be given to the compiler before it can be used and given the left-hand side it's a function (mind the => two-letter string) from a type (we'll get to it in a moment) to Boolean since set == 4 will inevitably end as Boolean.
From set == 4 we can deduce that set can only be Int (so you can compare apples to apples) and hence we've got the type of set as Int.
The right-hand side of = of the val could also have been written as:
val Singleton4: Set = (set: Int) => set == 4
So, the Singleton4 val is an instance of a function Int => Boolean that's called Set. Set's declared as such somewhere above (lexicographically):
type Set = Int => Boolean
You could substitute Set to the type alias and end up with:
val Singleton4: Int => Boolean = (set: Int) => set == 4