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.
Related
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'm trying to figure out the difference between def and var/val when declaring a function in Scala.
Say we have a function:
scala> def f(x: Int) = { x * 2 }
f: (x: Int)Int
And another function g:
scala> var g = (x:Int) => x*2
g: Int => Int = <function1>
Apparently they are the same in the following way:
scala> f(2)
res0: Int = 4
scala> g(2)
res1: Int = 4
However, I could do
g = f
g: Int => Int = <function1>
but not
scala> f = g
<console>:13: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
val $ires6 = f
^
<console>:10: error: reassignment to val
f = g
^
Question 1: why does this happen? I'm guessing that def maps to val.
Question 2: if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
I then try:
scala> def three( timetwo:(Int) => Int ) = { timetwo(3) }
three: (timetwo: Int => Int)Int
scala> three(g)
res47: Int = 6
scala> three(f)
res48: Int = 6
Question 3: does it mean (x: Int)Int is the same as Int => Int = <function1>? If so, is there some situation that we should favor one over the other?
Things is getting wired with the _ (underscore),
scala> three(f _)
res49: Int = 6
scala> three(g _)
<console>:11: error: type mismatch;
found : () => Int => Int
required: Int => Int
three(g _)
^
Question 4: why does this happen? What's the usage of _(underline) in Scala?
why does this happen? I'm guessing that def maps to val.
def is a method (in JVM terms) so it doesn't make sense to assign it.
The parser is then confused and it ultimately tries to save the day by interpreting the assignment f = g as
val $ires6 = f
f = g
Both statements are illegal, so you get two errors:
you can't assign a method to a val without an explicit type annotation or a _ expansion - see below)
you can't reassign a val (in case you are wondering, $ires6 is a fresh val introduced by the REPL)
if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
The difference is that val cannot be reassigned (i.e. it's a constant reference), whereas var can (i.e. it's a mutable reference).
More on the subject here: What is the difference between a var and val definition in Scala?
does it mean (x: Int)Int is the same as Int => Int = ? If so, is there some situation that we should favor one over the other?
Methods and functions are not the same, although the compiler does its best to make you believe they are, through a transformation called eta-expansion. In some cases such transformation can be performed automatically, in some others you need to be explicit and trigger it with a trailing _.
In your specific example (passing a method where a function is expected) the expansion can been performed automatically.
You can read this Q/A for a more in-depth discussion about which style to prefer.
why does this happen? What's the usage of _(underline) in Scala?
The underscore (_) has many uses in scala, one of which is the one I mentioned before, i.e. triggering the eta expansion of a method into a function.
That's a special syntax for methods, so you simply can't apply it to a function, as it would make no sense.
That's why you can do f _ (which will turn the f method into a function), but you can't do g _ (since g it's already a function).
I have a function defined like
def counter(x: Int) = {
var i = x
() => {
i = i + 1
println(i)
}
}
val count = counter(0)
So count is a function taking no parameter returning Unit. Then the parenthesis could be omitted when calling count. But if I call it by just saying count, i in fact will not be added and nothing happens. In the meantime, a compiler warning will be given like "A pure expression does nothing you may be omitting the parenthesis".
If I call it with parentheses like count(), everything is all right and increased i will be printed.
Why saying count doesn't work? Thank you.
You can't call function without parentheses. In scala you can call method without arguments with no parentheses. Method, but not function.
Actually "call function" means "call method apply of object of type FunctionN" in scala.
So count() means count.apply(). You can call method apply with no parentheses like this: count.apply.
Your counter(x:Int) method actually returns the function () => { ... } you have defined (which returns Unit and generates the compiler warning).
So by calling count with parentheses, you actually execute the function.
If I desugar type inference, you obtain:
def counter(x: Int): () => Unit = {
var i = x
() => {
i = i + 1
println(i)
}
}
val count: () => Unit = counter(0)
A Function0 does not correspond to a parameterless method exactly. That is to say:
val returnOne = () => 1
// approximates
def returnOne() = 1
// rather than
def returnOne = 1
In fact, once you lift a parameterless method to a Function0 the parameterless method behavior is lost:
// Define a parameterless method
scala> def returnOne = 1
returnOne: Int
// Every time you reference the method it is evaluated
scala> returnOne
res2: Int = 1
// Lift the method to a Function0
scala> returnOne _
res3: () => Int = <function0>
// Now a reference to the lifted method evaluates to the lifted method
scala> res3
res4: () => Int = <function0>
// And you have to invoke it explicitly
scala> res3()
res5: Int = 1
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.
What exactly that declaration of method parameter means:
def myFunc(param: => Int) = param
What is meaning of => in upper definition?
This is so-called pass-by-name. It means you are passing a function that should return Int but is mostly used to implement lazy evaluation of parameters. It is somewhat similar to:
def myFunc(param: () => Int) = param
Here is an example. Consider an answer function returning some Int value:
def answer = { println("answer"); 40 }
And two functions, one taking Int and one taking Int by-name:
def eagerEval(x: Int) = { println("eager"); x; }
def lazyEval(x: => Int) = { println("lazy"); x; }
Now execute both of them using answer:
eagerEval(answer + 2)
> answer
> eager
lazyEval(answer + 2)
> lazy
> answer
The first case is obvious: before calling eagerEval() answer is evaluated and prints "answer" string. The second case is much more interesting. We are actually passing a function to lazyEval(). The lazyEval first prints "lazy" and evaluates the x parameter (actually, calls x function passed as a parameter).
See also
Scala Returning a void function with 0 parameters, ugly syntax?
Just to make sure there is an answer that uses the proper term: the Scala Language Specification uses the term call-by-name:
The type of a value parameter may be prefixed by =>, e.g. x: => T . The type of
such a parameter is then the parameterless method type => T . This indicates that
the corresponding argument is not evaluated at the point of function application, but
instead is evaluated at each use within the function. That is, the argument is
evaluated using call-by-name.
-- Section 4.6.1 of the Scala Language Specification
To add to Tomasz Nurkiewicz's answer above, the difference I encounter between () => Int and => Int is that the second allows calling with bare blocks:
scala> def myfunc(f : () => Int ) = println("Evaluated: " + f )
myfunc: (f: () => Int)Unit
scala> def myfunc2(f : => Int ) = println("Evaluated: " + f )
myfunc2: (f: => Int)Unit
scala> myfunc({1})
<console>:9: error: type mismatch;
found : Int(1)
required: () => Int
myfunc({1})
^
scala> myfunc2({1})
Evaluated: 1