Scala function that takes a multiple parameter anonymous function, as a parameter - scala

I have a function named sum that can take a single parameter anonymous function as a parameter, and two Integers.
def sum (f: Int => Int , a: Int, b: Int): Int =
{
if(a > b) 0 else f(a) + sum(f, a + 1, b)
}
sum((x: Int) => x , 2, 10)
How could I modify the function definition so that it can take a multiple parameter function, so I could call it like this:
sum((y: Int, i: Int) => y + i => x , 2, 10)
I know the function I have supplied would be pretty useless when passed a multiple parameter function.. but I am just looking for how it can be done..
Thanks

As simple as this:
def sum (f: (Int, Int) => Int , a: Int, b: Int): Int = ???
Or a curried version:
def sum (f: Int => Int => Int , a: Int, b: Int): Int = ???
Although you can curry any function just calling f.curried

Related

High-Order Function [duplicate]

This question already has answers here:
Currying syntax in scala
(2 answers)
Closed 5 years ago.
In the course of funcional programming with Scala, I saw two form of declaration of a def. But I don't know the diferences between them, and the name given for this. How I can get more information about this?
Declaration 1
def sum(f: Int => Int)(a: Int, b: Int): Int = ???
Declaration 2
def sum(f: Int => Int, a: Int, b: Int): Int = ???
First one is called the curried syntax.
You can apply the function partially, then results in returning of a new function.
scala> def sum(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int)(a: Int, b: Int)Int
scala> sum({x: Int => x + 1}) _
res10: (Int, Int) => Int = $$Lambda$1115/108209958#474821de
Second one is uncurried syntax but still we can apply the function partially even in this case.
scala> def sum(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int, a: Int, b: Int)Int
scala> sum({x: Int => x + 1}, _: Int, _: Int)
res11: (Int, Int) => Int = $$Lambda$1116/1038002783#1a500561
Again new function returned when applied partially.
There is no difference between above two declaration, Its just the syntactic sugar.

Currying syntax in scala

The syntax of currying in scala is for example
def f(x: Int, b: Int) = x + y
is
def f(x: Int)(b: Int) = x + y
And currying for sum to sum for given range a and b is
def sum(f: Int => Int, a: Int, b: Int) = {
...
}
sum(x=>x, 3, 6) // outcome is 18 (3+4+5+6)
is
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
}
sum(x=>x)(3, 6) // outcome is 18 (3+4+5+6)
But I don't understand why colon(:)
exists between (f: Int => Int) and (Int, Int)
in def sum(f: Int => Int): (Int, Int) => Int = {
instead of
def sum(f: Int => Int)(Int, Int) => Int = {
Your sum example is not curried. If you wanted it curried you'd do something like:
def sum(f: Int => Int)(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sum(f)(a + 1, b)
sum(x=>x)(3, 6) // res0: Int = 18
Your code defines a method that takes a single argument, def sum(f: Int => Int). That argument is a function that takes and Int and returns an Int. So no currying involved.
This sum method returns a function, : (Int, Int) => Int. This returned function takes 2 Ints and returns and Int. Invoking this sum method looks like currying, but it's not.
sum(x=>x)(3, 6)
Instead you are invoking sum() with a single argument (x=>x) and then invoking the returned function with two arguments (3,6).
(Int, Int) => Int between : and = specify the function's return type, i.e, it says sum will return another method of signature (Int, Int) => Int which takes two Int and returns another Int, and this is the signature of your inner sumF function:
You can rewrite this to the currying syntax as follows:
def sum(f: Int => Int)(a: Int, b: Int): Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF(a, b)
}
This will more or less do the same thing as the method defined in OP:
sum(x => x)(3, 6)
// res11: Int = 18
But these two definitions are not exactly the same, for instance, for the currying syntax defined here, if you want to generate a new method from it, you have to specify the variable type, like:
val mysum: (Int, Int)=> Int = sum(x => x)
But for the one in OP, it can be simply val mysum = sum(x => x) as the return type of sum as already been specified.

How are these two higher-order functions different?

The following two higher-order functions yield the same result, but I'm having trouble understanding the difference between the two. In fact, I don't understand 1). How can a function have two sets of ()?
1)
def sum(f: Int => Int) (a: Int, b: Int) = {
def loop(a: Int, acc: Int) : Int =
if (a > b) acc
else loop (a + 1, f(a) + acc)
loop (a, 0)
}
2)
def sum(f: Int => Int, a: Int, b: Int) = {
def loop(a: Int, acc: Int) : Int =
if (a > b) acc
else loop (a + 1, f(a) + acc)
loop (a, 0)
}
The first function is curried. Meaning you can partially apply it more easily. If you only use the first parameter list the function returns another function with the signature (Int, Int) => Int.
This is really useful if you need to pass a function with a specific function signature to higher order functions like map or reduce.
In other functional programming languages like Haskell, all functions are curried by default.
I wrote a whole blog post on this topic in case you're interested. You can read it right here.

How to compose to methods, without duplicate input arguments

Suppose I have two methods
scala> def a(a: Int, b: Int, c: Int) : Int = …
a: (a: Int, b: Int, c: Int)Int
scala> def b(i: Int) : Int = …
b: (i: Int)Int
How to define a method c, that is the composition of both ?
Unfortunately, the following code doen't compile :
def c = b(a)
You could convert method a to function and then use method andThen like this:
def a(a: Int, b: Int, c: Int) : Int = a + b + c
def b(i: Int) : Int = i * 2
val c = (a _).tupled andThen b
c(1, 1, 1)
// 6
Note that I have to convert function (Int, Int, Int) => Int to tupled version - ((Int, Int, Int)) => Int - here to use andThen. So result function c accepts Tuple3 as argument.
You could convert c to untupled version ((Int, Int, Int) => Int) using Function.untupled:
val untupledC = Function.untupled(c)
untupledC(1, 1, 1)
// 6
shapeless
There is no untupled method for function arity > 5.
You could also use shapeless toProduct/fromProduct methods for any arity like this:
import shapeless.ops.function._
import shapeless.ops.function._
val c = (a _).toProduct.andThen(b).fromProduct
Scalaz defines Functor instances for higher-arity functions, so you can just write
(a _).map(b)

scala, Passing an operator as argument of a function

I have this code:
for( i <- 0 to 8){
((numbers(i) - i)/3).abs + ((numbers(i) - i)%3).abs
}
and I would like to do, as the title says, something like this
for( i <- 0 to 8){
by3(numbers(i), i, /) + by3(numbers(i), i, %)
}
def by3(a: Int, b: Int, op: Int => Int) = ((a - b) op 3).abs
and probably also use a partially applied function for it.. but by now this would be possible to achieve? How?
First, you need to correctly define op as a function (specifically, a Function2)
def operate(a: Int, b: Int, op: (Int, Int) => Int ) : Int = (op ((a - b), 3)).abs
Operators in Scala are actually methods: + is a method of Int(and Long, Double, ...) in Scala OO foundation. Then, to pass a operator (method) as a function, you can lift it using the underscore notation:
operate(5, 3, _ + _)
To get rid of the underscores you need to define the functions as values.
val / = (a:Int, b: Int) => a / b
val % = (a:Int, b: Int) => a % b
def by3(a: Int, b: Int, fn: (Int, Int) => Int): Int = fn(a - b, 3).abs
(0 to 8).foreach(i => by3(numbers(i), i, /) + by3(numbers(i), i, %))
Edited/Update:
Being concise, the shortest way to do it is:
def doStuff(a: Int, b: Int, op: (Int, Int) => Int) = {op(a - b, 3).abs}
doStuff(4,1,_%_)
So you can doStuff(numbers(i), i, _ / _) + doStuff(numbers(i), i, _ % _)