Home > database >  How are Function Values processed in Higher Order Methods without definition in Scala?
How are Function Values processed in Higher Order Methods without definition in Scala?

Time:09-25

I want to understand how without defining the function variables methods still work. Code in case:

@ class Box(var x: Int) {
  def update(f: Int => Int) = x = f(x)
  def printMsg(msg: String) = {
    println(msg   x)

Now, if I perform the following calls, I get the desired output:

val b = new Box(1)
b.printMsg("Hello")

Hello1

b.update(i => i   5)
b.printMsg("Hello")

Hello6

In the update's definition, I do not tell it what to do. I just tell that assign the object's x property the result of f(x). But what f(x) does is not defined anywhere.

However, when I call the update() function, I pass on a function value: i => i 5. Does this mean that every time I call update, I define the function and keep in mind that this new function should take and return an Int?

I also read How Higher Order functions work in Scala post on Stackoverflow and I am not sure whether I got it right:

The function:

def higher_order(a:Int,b:Int,c:Int,f:(Int,Int)=>Int):Int=f(f(a,b),c)

takes 3 integers and one functional value which furthermore takes two integers and return one integer. The function f is not defined anywhere, however, the function higher_order is defined as: take 3 integers, take one functional value, return an integer and perform: f(f(a,b),c). The OP calls this function as: higher_order(1,2,3,_ _) and gets the result as 6.

The OP defines _ _ as the last argument in place of the function value parameter. So, is my thought process of defining the function value upon calling and ensuring that the args and return type matches is valid?

CodePudding user response:

Does this mean that every time I call update, I define the function

No, not necessarily. The update method takes a function as a parameter:

def update(f: Int => Int) = x = f(x)

When update is called, a function must be passed to it. One way is to define a lambda function where the function is called:

box.update(i => i   5)

This lambda function is created by the compiler once and then passed to update every time this code is called. Using a lambda function avoids the need to name the function and makes the code simpler and cleaner. (In this case it could even be update(_ 5) which is short but easily understood once you get to know Scala)

If you call update the same way in another part of the code, a second lambda function is created and passed to update.

box1.update(i => i   5) // First lambda function instance
box2.update(i => i   5) // This is a different function instance

But the function can also be defined once in advance and passed to update:

def add5(i: Int) = i   5

box.update(add5)

In this case the definition of add5 is independent of the call to update. And add5 is a single function that can be used multiple times which, in some cases, may be clearer:

box1.udpate(add5)
box2.update(add5)
box3.update(add5)

In both cases the type of f must be compatible with Int => Int. In the case of a lambda function, the compiler knows what type is expected and applies the appropriate types to the arguments if they are not provided. Thus when you pass i => i 5 to Int => Int, the compiler set the type of i to Int because that is what Int => Int expects. For the stand-alone add5 function the type of i must be supplied explicitly because the compiler doesn't know how this function is going to be used.


To break down the more complex high-order functions, just remember that functions are types like any other. They can be nested inside each other, used as arguments to other functions, and used to parameterise standard containers like List (e.g. List[Int => Int])

  • Related