J Markus
J Markus

Reputation: 58

Defining function using val

I know basic difference between defining functions in scala using def/val: if I use val, my function is defined once, as

scala> val valRandom = Random.nextInt
valRandom: Int = 2032538454

scala> valRandom
res0: Int = 2032538454

But my question is why Random.nextInt is calculated every time I use function like:

scala> val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = $$Lambda$1100/1597979904@1a6dc5ea

scala> valRandom2(0)
res2: Int = 486047489

scala> valRandom2(0)
res3: Int = 1573520480

Upvotes: 0

Views: 148

Answers (3)

user unknown
user unknown

Reputation: 36229

My repl responses:

scala>  val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = <function1>

so valRandom2 is something, which takes an Int and returns an Int, and is of type function1. For example:

scala>  val valRandom3 = (_:Int) + (_:Int) + Random.nextInt
valRandom3: (Int, Int) => Int = <function2>

This is of type function2.

The numbers (1, 2) indicate, how many parameters are passed into it. A function always returns one value, so that doesn't matter. Even if there is no return, because it is a procedure, probably called for a side effect, it implicitly returns Unit (). If it returns a List of something or a tuple, that is just one thing, which you have to break apart, to get to one of the multiple values.

A function isn't identic with a method. Function can be passed around and execution is delayed, while methods are invoked directly, but it's easy to pass a method as a function.

scala> def add (a: Int, b:Int) : Int = a + b
add: (a: Int, b: Int)Int

scala> def mul (a: Int, b:Int) : Int = a * b
mul: (a: Int, b: Int)Int

scala> def printIt (a: Int, b:Int, f:(Int, Int) => Int) = {
     |   val c = f (b, a) 
     |   println (s"b $b (X) a $a = c $c") 
     | }
printIt: (a: Int, b: Int, f: (Int, Int) => Int)Unit

scala> printIt (3, 4, add) 
b 4 (X) a 3 = c 7

scala> printIt (3, 4, mul) 
b 4 (X) a 3 = c 12

This example, while simple to understand, doesn't explain why it is useful, but useful examples are more complex to setup. But imagine a List which can sort numerical values. If you have a List of Employees, you can sort them by handing a function to the List, to get a Numeric out of an Employee, be it Employee.id, *.age, *.maxSalary (), .address.zipCode or whatever, which gives you maximal flexibility.

To the comment:

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala> val x = valRandom2 (0)
x: Int = -1231081

scala> val x = valRandom2 (0)
x: Int = 1421497830

Why is the print performed on declaration, but the nextInt on usage?

Because

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala> val x = valRandom2
x: Int => Int = <function1>

The result of the rhs is the function, which gets assigned to valRandom2 or x while the print was a side effect on declaration. The block returned, as its last expression, the function.

Swap the inner calls on valRandom2 and you get nothing (Unit).

Add the parameter Int to the second call:

scala>  val valRandom3 = {Random.nextInt; (_:Int) => println ("vR2 called") }
valRandom3: Int => Unit = <function1>

scala> valRandom3 (0)
vR2 called

scala> valRandom3 (0)
vR2 called

Upvotes: 0

Tim
Tim

Reputation: 27356

In valRandom2 the random offset is computed inside the function body, so it is computed every time the function is called.

You need to compute the random offset outside the function, like this:

val valRandom3 = { val rand = Random.nextInt; (_:Int) + rand }

Upvotes: 0

Mahesh Chand
Mahesh Chand

Reputation: 3250

In your first approach,

scala> val valRandom = Random.nextInt
valRandom: Int = 2032538454

If you notice the type of valRandom is int. Basically, you have initialized valRandom using Random.nextInt.

But, in the second approach,

scala> val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = $$Lambda$1100/1597979904@1a6dc5ea

You notice the type of valRandom2 is mapping from Int -> Int valRandom2 is a function value, which is nothing but an anonymous function or a lambda expression.

So, it will always generate new value whenever you make a call to it.

The difference in both approaches is that first approach is creating a variable and assigning it random value. But in the second approach, you are calling anonymous function so it will evaluate every time

Upvotes: 2

Related Questions