Scala: Difference between function declarations [duplicate] - scala

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.

Related

Passing arguments to higher order functions

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

Function currying in scala

I’m learning scala and read this concept called ‘currying’. I know it is used to divide the parameters in a function and pass them one by one. So from what I understood I tried creating a simple basic currying function below:
def add_num(a:Int,b:Int)(c:Int):Int={a+b+c}
add_num(10,20)
add_num(10)
But it gives me an error when I call the function with values 10 and 20. What i understood is it will remember the values and then I can pass the third value as 10 separately. I’m unable to understand this concept. Can someone help me in understanding this concept in most basic terms.
Error is missing argument list for method add_num. Unsupplied methods are only converted to functions when a function type is executed.
A curried function is applied to multiple argument lists, instead of just
one. An example of a non-curried function, which adds two Int parameters, x and y:
scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int, y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3
A similar function that’s curried:
scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Int
scala> curriedSum(1)(2)
res5: Int = 3
What's happening here is that when you invoke curriedSum, you actually
get two traditional function invocations back-to-back. The first function
invocation takes a single Int parameter named x, and returns a function
value for the second function. This second function takes the Int parameter
y.
Here's a function named first that does in spirit what the first traditional
function invocation of curriedSum would do:
scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)Int => Int
Applying the first function to 1—in other words, invoking the first function
and passing in 1—yields the second function:
scala> val second = first(1)
second: Int => Int = <function1>
Applying the second function to 2 yields the result:
scala> second(2)
res6: Int = 3
These first and second functions are just an illustration of the currying
process. They are not directly connected to the curriedSum function. Nevertheless,
there is a way to get an actual reference to curriedSum's "second"
function. You can use the placeholder notation to use curriedSum in a partially
applied function expression, like this:
scala> val onePlus = curriedSum(1)_
onePlus: Int => Int = <function1>
The underscore in curriedSum(1)_ is a placeholder for the second parameter
list.2 The result is a reference to a function which, when invoked, adds one
to its sole Int argument and returns the result:
scala> onePlus(2)
res7: Int = 3
And here's how you'd get a function that adds two to its sole Int argument:
scala> val twoPlus = curriedSum(2)_
twoPlus: Int => Int = <function1>
scala> twoPlus(2)
res8: Int = 4

Higher Order Scala Func

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).

Explain some code which uses recursion and currying

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.

What are the applications/advantages of using partially applied functions in scala?

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.