I'm learning Programming Paradigms in my University and reading this course material provided by the lecturer that defined a function this way:
val double = (x: Int) => 2 * x
double: Int => Int = <function1>
But from my own studies I found and got used to defining the same function like this:
def d (x: Int) = 2 * x
d: (x: Int)Int
I'm new to Scala. And both definitions give a result of:
res21: Int = 8
Upon passing 4
as the parameter.
Now my main question is why would the lecturer prefer to use val
to define a function? I see it as longer and not really necessary unless using val
gives some added advantages that I don't know of. Besides I understand using val
makes some name a placeholder so later in the program, I could mistakenly write val double = 5
and the function would be gone!
At this stage I'm quite convinced I learned a better way of defining a function unless someone would tell me otherwise.
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.
In scala, functions are first class values. You can store function value, pass function as an argument and return function as a value from other function. You can create function by using def keyword. You must mention return type of parameters while defining function and return type of a function is optional.
In Scala the general rule is that you should always use a val field unless there's a good reason not to. This simple rule (a) makes your code more like algebra and (b) helps get you started down the path to functional programming, where all fields are immutable.
On the other hand, the val keyword represents a value. It's an immutable reference, meaning that its value never changes. Once assigned it will always keep the same value. Scala's val is similar to a final variable in Java or constants in other languages.
Strictly speaking def d (x: Int) = 2 * x
is a method, not a Function, however scala can transparently convert (lift) methods into Functions for us. So that means you can use the d
method anywhere that requires a Int => Int
Function.
There is a small overhead of performing this conversion, as a new Function instance is created every time. We can see this happening here:
val double = (x: Int) => 2 * x
def d (x: Int) = 2 * x
def printFunc(f: Int => Int) = println(f.hashCode())
printFunc(double)
printFunc(double)
printFunc(d)
printFunc(d)
Which results in output like so:
1477986427
1477986427
574533740
1102091268
You can see when explicitly defining a Function using a val
, our program only creates a single Function and reuses it when we pass as an argument to printFunc
(we see the same hash code). When we use a def
, the conversion to a Function happens every time we pass it to printFunc
and we create several instances of the Function with different hash codes. Try it
That said, the performance overhead is small and often doesn't make any real difference to our program, so def
s are often used to define Functions as many people find them more concise and easier to read.
In Scala, function values are monomorphic (i.e. they can not have type parameters, aka "generics"). If you want a polymorphic function, you have to work around this, for example by defining it using a method:
def headOption[A]: List[A] => Option[A] = {
case Nil => None
case x::xs => Some(x)
}
It would not be valid syntax to write val headOption[A]
. Note that this didn't make a polymorphic function value, it is just a polymorphic method, returning a monomorphic function value of the appropriate type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With