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
Related
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
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am new to scala, I have a use case where I want to define a partial function to add three numbers in which one number is constant and two
numbers can be passed as inputs and define another method which can take the partial
function as input and gives its cube as result.
Well... That depends on where is your constant coming from?
Choice 1 - Your function forms a closure with a constant present in scope.
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
pf((5, 10))
Choice 2 - Your function has a local constant.
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + 10
}
pf((5, 10))
Also, as many others pointed out - this does not look like a use case of partial function. Are you sure that you want a Partial Function and not a partially applied function ?
if you were looking for a partially applied function then,
// first you need a curried function
// Curries function are function which can take parameters in steps to build intermidatary functions.
def normalDef(c: Int)(x: Int, y: Int): Int = c + y + x
// normalDef: normalDef[](val c: Int)(val x: Int,val y: Int) => Int
// now you can "partially apply" this "curried" function to your partially applied function
val addTo10PartiallyApplied = normalDef(10) _
// addTo10PartiallyApplied: (Int, Int) => Int = $Lambda$1240/1924827254#46202553
val total = addTo10PartiallyApplied(1, 2)
// total: Int = 13
The following partial function adds 12345 to each number in the tuple passed to it
scala> val addConstantTo: PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + 12345
| }
addConstantTo: PartialFunction[(Int, Int),Int] = <function1>
scala> addConstantTo((12, 34))
res4: Int = 12391
This expands on the concept, by programmatically defining a partial function which adds any number to the elements of a tuple:
scala> def addTo(c: Int): PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + c
| }
addTo: (c: Int)PartialFunction[(Int, Int),Int]
scala> val pf = addTo(3)
pf: PartialFunction[(Int, Int),Int] = <function1>
scala> pf((1, 2))
res5: Int = 6
Let that sink in for a bit :)
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.
In this function "f" :
def f(x: => Int) : Int = x * x * x //> f: (x: => Int)Int
var y = 0 //> y : Int = 0
f {
y += 1
println("invoked")
y
} //> invoked
//| invoked
//| invoked
//| res0: Int = 6
"f" is invoked same amount of times as "x" parameter is multiplied.
But why is function invoked multiple times ?
Should "f" not expand to 1 * 1 * 1 not 1 * 2 * 3 ?
Your x is not a function, it is a by-name parameter, and its type is a parameterless method type.
Parameterless method type means the same as def x, something that is evaluated every time you reference it. By reference, we mean x and not x.apply() or x().
The expression you're passing to your function f is evaluated every time x is referenced in f. That expression is the whole thing in braces, a block expression. A block is a sequence of statements followed by the result expression at the end.
Here's another explanation: https://stackoverflow.com/a/13337382/1296806
But let's not call it a function, even if it behaves like one under the covers.
Here is the language used in the spec:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters
It's not a value type because you can't write val i: => Int.
It was a big deal when they changed the implementation so you could pass a by-name arg to another method without evaluating it first. There was never a question that you can pass function values around like that. For example:
scala> def k(y: => Int) = 8
k: (y: => Int)Int
scala> def f(x: => Int) = k(x) // this used to evaluate x
f: (x: => Int)Int
scala> f { println("hi") ; 42 }
res8: Int = 8
An exception was made to "preserve the by-name behavior" of the incoming x.
This mattered to people because of eta expansion:
scala> def k(y: => Int)(z: Int) = y + y + z
k: (y: => Int)(z: Int)Int
scala> def f(x: => Int) = k(x)(_) // normally, evaluate what you can now
f: (x: => Int)Int => Int
scala> val g = f { println("hi") ; 42 }
g: Int => Int = <function1>
scala> g(6)
hi
hi
res11: Int = 90
The question is how many greetings do you expect?
More quirks:
scala> def f(x: => Int) = (1 to 5) foreach (_ => x)
f: (x: => Int)Unit
scala> def g(x: () => Int) = (1 to 5) foreach (_ => x())
g: (x: () => Int)Unit
scala> var y = 0
y: Int = 0
scala> y = 0 ; f { y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
scala> y = 0 ; g { y += 1 ; println("hi") ; () => y }
hi
y: Int = 1
scala> y = 0 ; g { () => y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
Functions don't cause this problem:
scala> object X { def f(i: Int) = i ; def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
res12: Int = 0
scala> trait Y { def f(i: Int) = i }
defined trait Y
scala> object X extends Y { def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object X of type (i: => Int)Int
and method f in trait Y of type (i: Int)Int
match argument types (Int)
X.f(0)
^
Compare method types:
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#method-types
This is not a pedantic distinction; irrespective of the current implementation, it can be confusing to think of a by-name parameter as "really" a function.
Another way of saying what has already been said is that inside f you invoke the function x three times. The first time it increments the y var and returns 1. The second time it again increments y returning 2 and the third time it again increments y and returns 3.
If you want it invoked only once then you may want to do something like this:
def f(x: => Int) : Int = x * x * x
var y = 0
lazy val xx = {
y += 1
println("invoked")
y
}
f {xx}
This will print 'invoked' only once and result in a returned value of 1.
x: T means need a T value.
x: => T means need a T value, but it is call by name.
x: () => T This means need a function given nothing to T
However, this question is not related to the difference between function and method.
The reason is call by name is invoked every time you try to use it.
change to call by value def f(x: Int) : Int, it will only invoke once.
Because you increment y by 1 every time the argument is used inside f
The result which your function f() returns is changing, because there is a global variable that is incremented with every subsequent call to that function.
the x in f(x: => Int) is interpreted as "some function that returns Int". So it has to be called 3 times to evaluate the x*x*x expression. With every call, you increment the global variable and return the result, which is how you arrive at three subsequent natural numbers (because the global variable is initialized to 0). Hence 1*2*3.