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.
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:
Understanding Currying in Scala
(3 answers)
Closed 4 years ago.
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF
}
def sumCubes = sum(a => a * a * a)
sumCubes // output Function2
sumCubes(1,10) // output 3025.
sumCubes() // doesn't work
I feel I dont understand currying well enough. In the first statement , we are calling sumCubes without parameters , hence sum gets called with the anonymous function as parameter and returns a function2.
Whats really happening in 2nd and 3rd invocation ,
Why are we able to do
sum(a => a * a * a)(1,10)
but not
sumCubes()(1,10)
My understanding is that in sum(a => a * a * a)(1,10) , we are partially applying sum to the anonymous function, which returns a Function2 ,which is applied to the second pair of parameters (1,10) and hence we are getting 3025,
However the same should happen in case of sumCubes()(1,10) , invoking sumCubes without parameters first , would inturn invoke sum with the anonymous function and the Function2 returned would be applied to (1,10)
Why does sumCubes(1,10) work but not sumCubes()(1,10) , shouldn't sumCubes and sumCubes() mean the same thing , invocation of function sumCubes. Also if a simple reference sumCubes is invoking it , how can I pass it around. I feel like I am not understanding something fundamental about Scala.
Scala's methods can have multiple argument lists.
For example, here is a method foo that has ten argument lists, of which the first seven are empty:
def foo()()()()()()()(a: Int)(b: Int)(c: Int): Int = a + b + c
You can invoke it as follows:
println(foo()()()()()()()(1)(20)(300))
and it will print 321.
Note that when you invoke a method, the number of argument lists, as well as the number of arguments in each list (and also their types) have to match the declaration.
Another example. The following method has two argument lists:
def bar(i: Int)(f: Int => Int) = f(i)
you can invoke it as follows:
bar(42)(x => x * x)
but not as
bar()(x => x * x)
bar()(42)(x => x * x)
bar(42)()
or anything like it.
Completely analogously, if you have defined a method with zero argument lists
def baz = (x: Int) => x * x
then you must invoke it with zero argument lists too:
baz
Since it returns an Int => Int function, you can of course apply the result to an Int:
baz(42)
which is the same as (baz)(42), but you cannot do the following:
baz()(42)
because baz itself has no argument lists, and () does not contain a single integer argument.
Note that all of the above is actually a simplification: under certain circumstances, methods that have an empty argument list can be called without parentheses, i.e. def foo(): Unit = ... can be invoked as foo, without (). This is a somewhat strange feature, and I can't say exactly why it's there. My best guess would be: it has something to do with java-interop, where you really want to omit parentheses on zero-ary getters.
So I have this function in Scala:
def f(a: Int)(b: Int)(c: Double)(d: Double): Double = a * c + b * d
The question is What are the three types that make the following statements compile.
def g: <Type1> = f(1)(2)(3.0)
def h: <Type2> = f(1)(2)
def k: <Type3> = f(1)
I'm still new to Scala and I am not really understanding the concept of currying. Maybe an answer to this question with some explanation will really help me. Thanks.
First, one main thing: function that takes two parameters a and b and returns a value c can be viewed as a function that takes an a and returns a function that takes b and returns c. This "change of point of view" is called currying.
Imagine a function that sums up two numbers. You give it 2 and 3, it returns 5. It can be viewed as a function that takes one number and returns a function from a number to a number. You give it a 2, it returns a function that takes some number and adds 2 to it.
Now, some types that you requested:
// pseudocode!
def g: Double => Double
= f(1)(2)(3.0) // we supply three params and are left with only one, "d"
= (d: Double) => 1 * 3.0 + 2 * d // we comply with g's type
def h: Double => Double => Double // or (Double, Double) => Double
= f(1)(2) // we supply two params and are left with two more, "c" and "d"
= (c: Double)(d: Double) => 1 * c + 2 * d // we comply with h's type
def k: Double => Double => Double => Double // or (Double, Double, Double) => Double
= f(1) // we supply one param and are left with three more, "b", "c" and "d"
= (b: Double)(c: Double)(d: Double) => 1 * c + b * d // we comply with k's type
Currying IMO is one of the most confusing concepts in Scala. The term itself comes from functional programming paradigm and, according to wikipedia, is
the technique of translating the evaluation of a function that takes
multiple arguments (or a tuple of arguments) into evaluating a
sequence of functions, each with a single argument.
which means that function call f(a, b, c) is represented by f(a)(b)(c). Looks like Scala? Not exactly. Here we have three function calls, each of them returns another function. Type of f (in Scala speak) is Int => (Int => (Double => (Double => Double))). Let's look at your f:
scala> def f(a: Int)(b: Int)(c: Double)(d: Double): Double = a * c + b * d
f: (a: Int)(b: Int)(c: Double)(d: Double)Double
As you see, there are no arrows here. What we have here is a method with multiple parameter lists. Method has no value and can't be assigned or passed anywhere, it belongs to an object. Function, on the other hand, is an object and can be assigned or passed to another method or function. In most cases omitting parameter lists is not allowed for methods:
scala> f(0)
<console>:01: error: missing argument list for method f
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `f _` or `f(_)(_)(_)(_)` instead of `f`.
There is one exception though as error message implies: if f(0) is placed in a functional context Scala will perform automatic eta-expansion, which means it will convert your method to a function:
scala> val fl: (Int => (Double => (Double => Double))) = f(0)
fl: Int => (Double => (Double => Double)) = $$Lambda$1342/937956960#43c1614
where eta-expansion means literally this:
scala> val fl: (Int => (Double => (Double => Double))) = (b => (c => (d => f(0)(b)(c)(d))))
fl: Int => (Double => (Double => Double)) = $$Lambda$1353/799716194#52048150
Another (explicit) way to convert a method to a curried function is by using placeholder (which will give you correct types right away):
scala> f _
res11: Int => (Int => (Double => (Double => Double))) = $$Lambda$1354/1675405592#4fa649d8
scala> f(0) _
res12: Int => (Double => (Double => Double)) = $$Lambda$1355/1947050122#ba9f744
Also be aware that:
def g: Int => (Double => (Double => Double)) = f(0)
is in fact
def g: Int => (Double => (Double => Double)) = (b => (c => (d => f(0)(b)(c)(d))))
i.e. it's a method g, which creates a function on the fly and returns it. So g(0) means "call method g without parameters, get back a function and apply it to 0".
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).
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.