I'm trying to write a tail recursive function in the below way, but the compiler is throwing an error:
Too many arguments for method apply: (v1: Int)Int in trait Function1
else factorial(x-1, x*acc)
I had tried replacing Function1 with Function2 and gave Function2[Int, Int, Int] = new Function2[Int, Int, Int]
But it still threw me the same error. Can someone point out where i'm going wrong?
import scala.annotation.tailrec
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
#tailrec override def apply (x:Int, acc:Int=1): Int = {
if (x<=1) acc
else factorial(x-1, x*acc)
}
}
factorial(5)
You apply inside Function1 must take only one param, when you are passing two.
You can rewrite it as follows:
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
def apply (x:Int): Int = {
#tailrec def loop(x: Int, acc: Int = 1): Int = {
if (x<=1) acc
else loop(x-1, x*acc)
}
loop(x)
}
}
Function1 represents a function with a single parameter (the second one is for the output)
So you need to define your apply method with a single parameter, and then, inside it, do the recursion using a nested function:
import scala.annotation.tailrec
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
override def apply(x: Int): Int = {
#tailrec
def go (x: Int, acc: Int = 1) : Int = {
if (x<=1) acc
else go(x-1, x*acc)
}
go(x)
}
}
factorial(5)
You can see this answer which is a great explanation of your issue. Your problem is you are trying to define apply as tail-recursive but you are not calling itself in the recursive call, you are calling factorial instead.
First off, you should use Function2 as your type for apply likewise:
import scala.annotation.tailrec
import scala.annotation.tailrec
var factorial: Function2[Int, Int, Int] = new Function2[Int, Int, Int] {
#tailrec override def apply (x:Int, acc:Int=1): Int = {
if (x<=1) acc
else apply(x-1, x * acc)
}
}
And then, if you get the error could not optimize #tailrec annotated method apply: it contains a recursive call targeting a supertype, you should call apply recursively as for a function to be tail recursive it always should be called exactly itself as the last statement.
scala> factorial(5, 1)
res3: Int = 120
Function2 take 3 type parameters. Last one is the output type.
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
val fac: Function2[Int, Int, Int] = new Function2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = if (v1 == 1) v2 else apply(v1 - 1, v1 * v2)
}
// Exiting paste mode, now interpreting.
fac: (Int, Int) => Int = <function2>
scala> fac(5, 1)
res1: Int = 120
You can syntactic sugar (function syntax in scala using =>) instead of using interface/trait Function2.
scala> :paste
// Entering paste mode (ctrl-D to finish)
val fac: (Int, Int) => Int = (acc, c) => if (c == 1) acc else fac(acc * c, c - 1)
// Exiting paste mode, now interpreting.
fac: (Int, Int) => Int = $$Lambda$1092/1204822967#5c83ae01
scala> fac(1, 5)
res0: Int = 120
Or, if you like some syntactic sugar, you can write it:
val f: (Int) => BigInt = (x) => {
if (x <= 1) 1
else x * f(x - 1)
}
println(f(30))
Or true tail-recursive function:
val f: (Int) => BigInt = (x) => {
#tailrec
def helper(x: Int, acc: BigInt = 1): BigInt = {
if (x <= 1) acc
else helper(x - 1, x * acc)
}
helper(x)
}
println(f(30))
Related
I am trying to pass the partial function as input to square function.
What is worng with the following code?
package PartialFunction
object PartialFunctionSum {
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
def square(cb:(Int, Int) => Int): Unit = {
println(cb(5,10))
}
def main(args: Array[String]): Unit= {
square(pf)
}
}
A PartialFunction is a Function1 (a => b) and square needs a Function2 ((a,b) => c)
One way to accomplish what you want to do is changing cb type to Function1.
object PartialFunctionSum extends App {
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
def square(cb:((Int, Int)) => Int): Unit = {
println(cb(5,10))
}
square(pf)
}
Also, anywhere where you need a FunctionX, you can define a PartialFunction, so
square {
case (x, y) => x + y + yourConstant
}
Or transform your PartialFunction in a Function2 with a lambda
square( pf.apply(_, _) )
Anywhere you need a function you can a pass a PartialFunction,
Your problem is with square definition:
def square(cb:(Int, Int) => Int): Unit = {
println(cb(5,10))
}
That means that cb is a function that receives two Ints and returns another Int.
Just change square signature as follows:
def square(cb: ((Int, Int)) => Int): Unit = {
println(cb(5 -> 10))
}
And now your types are compatible and the rest of your code works as you expected.
(Int, Int) => Int is an instance of Function2[Int, Int, Int](a Function that takes 2 Int parameters and returns an Int), not PartialFunction[(Int, Int), Int] (a partial function that takes an input of type (Int, Int) and returns an Int)
If you want to pass your parameters as a Tuple then:
def square(cb:PartialFunction[(Int, Int),Int]): Unit = {
println(cb((5,10)))
}
Example:
def square(cb:PartialFunction[(Int, Int),Int]): Unit = {
println(cb((5,10)))
}
square: (cb: PartialFunction[(Int, Int),Int])Unit
scala> square{case (i, j) => i * j}
50
The following:
val add = (a: Int, b: Int) => a + b
gets converted to:
object add extends Function2[Int, Int, Int] {
def apply(a: Int, b: Int) = a + b
}
while
val a1 = add(_: Int, 3)
gets converted to:
object a1 extends Function1[Int, Int] {
def apply(x: Int): Int = {
add(x, 3)
}
}
But when I do:
scala> val a2 = add _
a2: () => (Int, Int) => Int = <function0>
And then call a2, it throws an error:
scala> a2(1, 2)
<console>:11: error: too many arguments for method apply: ()(Int, Int) => Int in trait Function0
a2(1, 2)
^
Why is this? Why does the following work?
a2()(1, 2)
add is already a Function2[Int, Int, Int]. If you want a2 to have the same type, then a simple assignment will suffice.
scala> val a2 = add
a2: (Int, Int) => Int = <function2>
scala> a2(1, 2)
res3: Int = 3
What you're thinking of is eta-expansion of a method into a function. If we had:
def add(a: Int, b: Int): Int = a + b
Then, we would use add _ to get the eta-expansion to assign to a value.
scala> def a2 = add _
a2: (Int, Int) => Int
scala> a2(1, 2)
res4: Int = 3
But add is already a function, so the underscore has a different meaning. add is now a value and not a method. Since add is a value, it is like a parameter-less method that returns a Function2[Int, Int, Int]. And if we try to get the eta-expansion of that, we get () => Function2[Int, Int, Int].
Consider a simpler example where we have a simple val a = 1. a is essentially the same as a parameter-less method that returns 1 (def a = 1). If I try to obtain the eta-expansion, I will get () => Int.
scala> val a = 1
a: Int = 1
scala> val a2 = a _
a2: () => Int = <function0>
Why does andThen only exist for single argument functions in Scala?
The following code works:
val double = (x: Int) => x * 2
val timesFour = double andThen double
But why is there no andThen method for multi argument functions?
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
<console>:10: error: value andThen is not a member of (Int, Int) => Int
Surely it is trivial to add this method. Is there a reason it been omitted from the standard library?
I have just noticed it is easy to work around with the following:
val multiplyAndDouble = multiply.tupled andThen double
val res = multiplyAndDouble(1, 3) // res = 6
I can't speak as to why Function2 doesn't supply and andThen, but Scalaz defines Functor instances for functions of various arities where map is equivalent to andThen, meaning you could write
val multiplyAndDouble = multiply map double
There is a similar question here:
Scala API 2.10.*: Function2.andThen what happened to?, but there is also no answer. In my opinion it is possible. Here is working example for Scala 2.11.1:
object TestFunction2 {
def main(args: Array[String]): Unit = {
val double = (x: Int) => x * 2
val timesFour = double andThen double
println(timesFour(2)) // prints 8
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
println(multiplyAndDouble(1, 3)) // prints 6
}
implicit def toFunc2(function2: Function2[Int, Int, Int]): Func2[Int, Int, Int] = {
new Func2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = function2(v1, v2)
}
}
}
trait Func2[-T1, -T2, +R] extends Function2[T1, T2, R] {
def andThen[A](g: R => A): (T1, T2) => A = { (x, y) => g(apply(x, y)) }
}
Another way to write theons's answer is to use:
val multiplyAndDouble = double compose multiply.tupled
val result = multiplyAndDouble(2, 6) // res 24
How can I refer to one overload of a function? Does this require reflection?
----- Define two functions with the same signature
scala> def f( x:Int ) = x + 1
f: (x: Int)Int
scala> def g( x:Int ) = x + 2
g: (x: Int)Int
----- Define a function that returns one or the other
scala> def pick( a:Boolean ) = if (a) f _ else g _
pick: (a: Boolean)Int => Int
scala> pick(true)(0)
res24: Int = 1
scala> pick(false)(0)
res25: Int = 2
----- All good so far; now overload f to also take a String
scala> def f( x:String ) = x.toInt + 1
f: (x: String)Int
scala> def pick( a:Boolean ) = if (a) f _ else g _
pick: (a: Boolean)String with Int => Int
scala> pick(false)(0)
<console>:12: error: type mismatch;
found : Int(0)
required: String with Int
pick(false)(0)
^
I understand why this doesn't work. But how can I define pick to use the f that takes an Int, and ignore the f that takes a String?
Again, I don't want to write a function that calls either f or g. I want to write a function that returns f or g, which I can then call gazillions of times.
Just add a type annotation:
def pick( a:Boolean ) = if (a) f(_: Int) else g(_: Int)
Supplement: Don't be fooled by how the REPL constructs what it runs:
scala> :pa
// Entering paste mode (ctrl-D to finish)
object Foo {
def f(i: Int) = i.toString
def f(s: String) = s
def pick( a:Boolean ) = if (a) f _ else "nope"
}
// Exiting paste mode, now interpreting.
<console>:10: error: ambiguous reference to overloaded definition,
both method f in object Foo of type (s: String)String
and method f in object Foo of type (i: Int)String
match expected type ?
def pick( a:Boolean ) = if (a) f _ else "nope"
^
Using the REPL, the other answer to your question is, define the one you want last, because it becomes most specific:
scala> def f(s: String) = s
f: (s: String)String
scala> def f(i: Int) = i.toString
f: (i: Int)String
scala> f _
res0: Int => String = <function1>
After having discovered that currying multi parameter-groups method is possible, I am trying to get a partially applied function which requires implicit parameters.
It seams not possible to do so. If not could you explain me why ?
scala> def sum(a: Int)(implicit b: Int): Int = { a+b }
sum: (a: Int)(implicit b: Int)Int
scala> sum(3)(4)
res12: Int = 7
scala> val partFunc2 = sum _
<console>:8: error: could not find implicit value for parameter b: Int
val partFunc2 = sum _
^
I use a singleton object to create this partially applied function and I want to use it in a scope where the implicit int is defined.
That is because you don't have an implicit Int in scope. See:
scala> def foo(x: Int)(implicit y: Int) = x + y
foo: (x: Int)(implicit y: Int)Int
scala> foo _
<console>:9: error: could not find implicit value for parameter y: Int
foo _
^
scala> implicit val b = 2
b: Int = 2
scala> foo _
res1: Int => Int = <function1>
The implicit gets replaced with a real value by the compiler. If you curry the method the result is a function and functions can't have implicit parameters, so the compiler has to insert the value at the time you curry the method.
edit:
For your use case, why don't you try something like:
object Foo {
def partialSum(implicit x: Int) = sum(3)(x)
}
scala> object MySingleton {
| def sum(a: Int)(implicit b: Int): Int = { a+b }
|
|
| def caller(a: Int) = {
| implicit val b = 3; // This allows you to define the partial below
| def pf = sum _ // and call sum()() without repeating the arg list.
| pf.apply(a)
| }
| }
defined module MySingleton
scala> MySingleton.caller(10)
res10: Int = 13