I am new to Scala Higher Order Function and i am kind of confuse in this.
Up to my knowledge , HOF can take functions as arguments like
val c = (x:Int)=> x + 3
here it means it take one argument of type Int and returns Int.
But i am not able to understand the below code as it take a functions as argument of type Int => Int but means it takes one argument and returns Int , but while implementing this they are sending a function which takes two Int args.
def calculate(f: Int => Int, a: Int, b: Int) =
if (b != 0) f(a, b) else throw Exception("Divide by 0")
def divide(a: Int, b: Int) = a / b
calculate(divide, 2, 0) // => Exception
calculate(divide, 4, 2) // => 2
Can someone help me in understanding this.
I appreciate if someone can share some code links where i can understand more about HOF.
def divide(a: Int, b: Int): Int = a / b
divide is a function (actually a method) that takes 2 Ints and returns 1 Int. It can also be written like this.
val divide = (a:Int, b:Int) => a/b
In this case it is an actual function, but the difference between method and function need not concern us here.
def calculate(f: (Int, Int) => Int, a: Int, b: Int): Int = ...
calculate take 3 arguments. The first, f, is a function that takes 2 Ints and returns 1 Int. (Note the correct signature.)
calculate(divide, 77, 7)
Invoke calculate with divide as its first argument. Inside the calculate code divide is referenced (renamed) as f and invoked as such. So f(a, b) is really divide(77, 7).
Related
how do I pass different parameters for my function inside a higher order function. my code below.
val sum = (a: Int, b:Int) => a + b
val x = 7
val y = 9
def sq (x: Int, y: Int, f: (Int, Int)=> Int): Int = {
x + y * f(a,b)
}
println(sq(x,y,sum(2,3)))
This doesn't work and throws an error that 'a' is not defined.
The parameter list for sq looks ok.
The call to sq isn’t right, the function would get evaluated before it gets passed in. Assuming it got by the compiler, which of course it doesn’t.
Passing in a function does not mean its arguments come along for the ride. Passing in a function means the caller may not know what arguments to use or even if the function should be called. The sq function has to supply arguments when it calls it. a and b mean nothing outside the definition of sum. sq could supply x and y as arguments to sum.
Just as an addition to #Nathan answer. This example would make sense:
val sum = (a: Int, b:Int) => a + b
def sq (x: Int, y: Int, f: (Int, Int)=> Int): Int = {
x + y * f(x, y)
}
val x = 7
val y = 9
println(sq(x,y,sum))
This would be evaluated in your sgfunction like:
7 + 9 * sum(7, 8)
I hope this makes sense.
In addition to the #Nathan Hughes answer, if you want to pass the different argument to the sum function on each call you need to change your sq method like
def sq (x: Int, y: Int, f: (Int, Int)=> Int): (Int, Int)=> Int = {
x + y * f(_: Int, _:Int)
}
Insted of expecting the int from the sq method return partially applied function of type (Int, Int) => Int from `sq' then pass other argument to that function like,
sq(10, 20, sum)(1, 2) // 1st approach
//2nd approach would be
//You can hold the function in another variable and call that function with other arguments
val partialSum = sq(10,20, sum)
partialSum(1, 2)
and you will get your result.
Or if you still want that sq method should return Int, you can define your sq method like
def sq (x: Int, y: Int, f: (Int, Int)=> Int)(a:Int, b:Int):Int = {
x + y * f(a, b)
}
scala> sq(10,20, sum)(1,2)
res2: Int = 70
This question already has answers here:
Differences between these three ways of defining a function in Scala
(3 answers)
Closed 6 years ago.
I am new to Scala, below are three function declarations that are confusing to me:
First
scala> def sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int
Second
scala> def sum (a: Int, b: Int) = a + b
sum: (a: Int, b: Int)Int
Third
scala> val sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int = <function2>
I know that the second one is method, third one is a function literal. My confusion is with the first declaration, is it a normal function or is it a some other syntax that I do not understand? An explanation would be appreciated.
EDIT
Also, when I try to create a partially applied function using the first declaration I get this:
scala> val anotherSum = sum _
anotherSum: () => (Int, Int) => Int = <function0>
Which I expected to be of type Function2 as sum has 2 parameters.
The first and second declarations declare different things. It's not the same thing with different syntax.
scala> def sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int
Here, you define a method named sum that takes no parameters and returns a function that takes two Int parameters and returns an Int.
So, sum is a method that returns a function that adds two numbers.
scala> def sum (a: Int, b: Int) = a + b
sum: (a: Int, b: Int)Int
Here, you define a method named sum that takes two Int parameters and that returns an Int.
So, sum is a method that adds two numbers.
The difference is that in the first version, sum takes no parameters and returns a function, and in the second, sum takes two parameters and returns an Int. Two very different things!
The third:
scala> val sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int = <function2>
Here you define a value named sum that is a Function2, in other words, a function that takes two Int parameters and returns an Int.
So, sum is a value that is of type Function2, and refers to a function that adds two numbers.
Extra:
scala> val anotherSum = sum _
anotherSum: () => (Int, Int) => Int = <function0>
Look carefully at the type. anotherSum is a function that takes no parameters that returns a function that takes two Int parameters that returns an Int.
You are not partially applying anything here. Section 6.7 Method Values of the Scala Language Specification explains what happens here.
I am going through the Scala School basics tutorial at
https://twitter.github.io/scala_school/basics.html.
I am trying to understand what the difference between these two definitions is.
Also, if someone could explain currying vs partial application in this context.
def multiply(m: Int)(n: Int): Int = m * n
and
def multiply(m: Int,n: Int): Int = m * n
The difference is only in how you actually call this methods. In second case your only choice is to pass both arguments at the same time, like multiply(2,2). In first case you can pass one argument and get function Int => Int and then call it with another argument:
val f: Int => Int = multiply(2) _
f(2) // 4
f(3) // 6
f(525) // 1050
The real power of curried methods is when the second argument is implicit so you don't have to pass it explicitly.
implicit val x = 2
def multiply(m: Int)(implicit n: Int): Int = m * n
multiply(5) //10
How is the method product used in this code ?
The result for this function is 3600
So product takes a function : f ,
f takes an Int parameter which returns an Int parameter.
But does (a: Int, b: Int) not indicate that a function which takes two Int parameters are returned ?
I'm confused as to what is is occuring in this line :
f(a) * product(f)(a + 1, b)
Complete function :
def product(f: Int => Int)(a: Int, b: Int): Int =
if(a > b) 1
else {
f(a) * product(f)(a + 1, b)
}
product(x => x * x)(3 , 5)
In Scala, methods can have multiple parameter lists. In this example, the method product has two parameter lists: (f: Int => Int) and (a: Int, b: Int).
The first parameter list contains one parameter named f, which is of type Int => Int (a function that takes an Int and returns an Int).
The second parameter list contains two parameters named a and b which are both of type Int.
The expressions product(f)(a + 1, b) and product(x => x * x)(3 , 5) simply call the method with all three parameters.
The advantage of this is that you can "call" product with only the first parameter list. What you'll then get is a function that you can call by supplying the second parameter list. For example:
val fn = product(x => x * x) // only the first parameter list is applied
fn(3, 5) // fn is a function which you can pass the second list
"Calling" product with only the first parameter list is called currying.
We have partially applied functions in Scala-
def sum(a:Int,b:Int,c:Int) = a+b+c
val partial1 = sum(1,_:Int,8)
I was wondering what are the advantages of using Partially applied functions. Or is it just a syntactical addition?
About partially applied function in general, the book "Programming in Scala, 2nd edition" mentions:
Another way to think about this kind of expression, in which an underscore
is used to represent an entire parameter list, is as a way to transform a
def into a function value.
For example, if you have a local function, such as sum(a: Int, b: Int, c: Int): Int, you can “wrap” it in a function value whose apply method has the same parameter list and result types.
scala> def sum(a: Int, b: Int, c: Int) = a + b + c
sum: (a: Int,b: Int,c: Int)Int
scala> val a = sum _
a: (Int, Int, Int) => Int = <function3>
(Here, a(1, 2, 3) is a short form for:
scala> a.apply(1, 2, 3)
res12: Int = 6
)
Although you can’t assign a method or nested function to a variable, or pass it as an argument to another function, you can do these things if you wrap the method or nested function in a function value by placing an underscore after its name.
The advantage is that sum(1,_,8) is less to type and read than x => sum(1,x,8).
That's all there is to it.
sum(1,_,8) is less to type and read than x => sum(1,x,8)
However, neither is legal; you must provide the parameter type.