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
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
val divide = (num: Double, den: Double) => {
num / den
}
//type of pafv1 is () => (Double,Double) => Double
val pafv1 = divide _
//type of pafv2 is Double => Double
val pafv2 = divide(_:Double,2)
Why type of pafv1 is not (Double,Double) => Double?
When divide is a simple method, type of pafv1 is (Double,Double) => Double.
I think the explanation comes from eta expansion.
Scala makes getters and setters of vals, which means divide is in fact a method def divide = (num: Double, den: Double) => { num / den }
When you do val pafv1 = divide _, this expands it into the eta expanded version of divide, namely () => (num: Double, den: Double) => { num / den }
Why is it doing eta expansion? Because you are trying to use a method as a value (you are partially evaluating _, forcing the result to be a function value).
That's weird... If you compile this piece of code:
class C {
val f = (n: Double, d: Double) => n / d
val pf = f _
}
with the -print flag, the desugared code is:
package <empty> {
class C extends Object {
private[this] val f: Function2 = _;
<stable> <accessor> def f(): Function2 = C.this.f;
private[this] val pf: Function0 = _;
<stable> <accessor> def pf(): Function0 = C.this.pf;
final <artifact> private[this] def $anonfun$f$1(n: Double, d: Double): Double = n./(d);
final <artifact> private[this] def $anonfun$pf$1(): Function2 = C.this.f();
def <init>(): C = {
C.super.<init>();
C.this.f = {
((n: Double, d: Double) => C.this.$anonfun$f$1(n, d))
};
C.this.pf = {
(() => C.this.$anonfun$pf$1())
};
()
}
}
}
Some observations:
The val f declaration is split into a private this val f: Function2 and into an <stable> <accessor> def f(): Function2.
The stable accessor method is wrapped into an anonymous function $anonfun$pf$1() that simply redirects all calls to C.this.f().
The pf eta-expands the parameterless $anonfun$pf$1() method into a function that takes no arguments and returns a Function2.
If I had to write down an equivalent piece of code that demonstrates "what actually happens", I'd probably write something like this:
class C2 {
var f: Function2[Double, Double, Double] = _
def fAccessor(): Function2[Double, Double, Double] = this.f
f = (n: Double, d: Double) => n / d
val pf = fAccessor _
}
Here you see that:
fAccessor is a method without arguments that returns a Function2
pf is eta-expansion of the accessor method fAccessor, which also takes zero arguments, and returns a Function2.
So, to conclude: for some weird reason, f _ is the eta-expansion of the otherwise invisible accessor method. I think this should not compile at all, looks like an abstraction leak (some synthetic implementation dependent method symbols appearing out of nowhere).
What you might have wanted:
val pf: Double => Double => Double = n => f(n, _)
I usually "wrap" the function in a case expression:
val divide = (num: Double, den: Double) => num / den
val partialDivide: PartialFunction[(Double, Double), Double] = {
case (num: Double, den: Double) if den != 0 => divide(num, den)
}
partialDivide(4, 2)
partialDivide(4, 0) // throws a `MatchError`
You can play around with this code on Scastie.
You can find a very thorough explanation of the topic here.
From the scala language specification one can read:
If e is a parameterless method … , e _ represents the function of type () => T, which evaluates e when it is applied to the empty parameterlist ().
This is what we see happening.
I want to implement some generic math functions with some flexible.
e.g. a function named meandot which declared as something like
object Calc {
def meandot[..](xs: Array[Left], ys: Array[Right])(implicit ..): Result
}
where meandot(xs, ys) = sum(x*y for x, y in zip(xs, ys)) / length
When I invoke the meandot without specialized type parameter, it should return a value with default type. e.g.
scala> Calc.meandot(Array(1, 2), Array(1, 1))
res0: Int = 1
If I invoke the meandot with specialized type parameter, it can return a proper value.
scala> Calc.meandot[Int, Int, Double](Array(1, 2), Array(1, 1))
res1: Double = 1.5
However, the first two type parameters in above are redundant. The only type I need to specialized is the return type. I want to invoke it simplified as
scala> Calc.meandot2(Array(1, 2), Array(1, 1))
res2: Int = 1
scala> Calc.meandot2[Double](Array(1, 2), Array(1, 1))
res3: Double = 1.5
And I found a way to implement it as following code, which using a proxy class MeanDotImp. But it seems not so elegant. So I wonder if there is any better solution to reduce the unwanted type parameter in a generic method?
trait Times[L, R, N] {
def times(x: L, y: R): N
}
trait Num[N] {
def zero: N = fromInt(0)
def one: N = fromInt(1)
def fromInt(i: Int): N
def plus(x: N, y: N): N
def div(x: N, y: N): N
}
abstract class LowTimesImplicits {
implicit val IID: Times[Int, Int, Double] = new Times[Int, Int, Double] {
def times(x: Int, y: Int): Double = x * y
}
}
object Times extends LowTimesImplicits {
implicit val III: Times[Int, Int, Int] = new Times[Int, Int, Int] {
def times(x: Int, y: Int): Int = x * y
}
}
object Num {
implicit val INT: Num[Int] = new Num[Int] {
def fromInt(i: Int): Int = i
def plus(x: Int, y: Int): Int = x + y
def div(x: Int, y: Int): Int = x / y
}
implicit val DOU: Num[Double] = new Num[Double] {
def fromInt(i: Int): Double = i
def plus(x: Double, y: Double): Double = x + y
def div(x: Double, y: Double): Double = x / y
}
}
object Calc {
def meandot[L, R, N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
implicit class MeanDotImp[L, R](val marker: Calc.type) {
def meandot2[N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
}
}
An alternative solution is similar to yours, but is a bit more straightforward: it first fixes the type parameter that you want to be able to set and then infers the other two. To achieve that we can declare a class with apply method:
class meandot[N] {
def apply[L, R](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = ??? // your implementation
}
Now, to avoid writing new meandot, we can define a method which just instantiates this class:
object Calc {
def meandot[N]: meandot[N] = new meandot[N]
}
Elegance of this approach is arguable, but it's quite simple and doesn't involve implicits. Here's a usage demo:
scala> Calc.meandot(Array(1,2,3), Array(4,5,6))
res0: Int = 10
scala> Calc.meandot[Double](Array(1,2,3), Array(4,5,6))
res1: Double = 10.666666666666666
I want IMPLICIT args in a higher order function, like:
func(arg1) { implicit (x, y) => x * y }
But the compiler says:
error: expected start of definition
val a = func("2", "4") { implicit (x, y) =>
^
java version "1.7.0_40"
Scala code runner version 2.10.2-RC2 -- Copyright 2002-2013, LAMP/EPFL
The runnable sample code:
object Test extends App {
new Test().run
}
class Test {
def run = {
val a = func("2", "4") { (x, y) => // It's OK
x * y
}
println("a: " + a)
val b = gunc("2", "4") { implicit x => { implicit y => // It's OK
x * y
}}
println("b: " + b)
}
def func(x: String, y: String)(f: (Int, Int) => Int) = f(x.toInt, y.toInt)
def gunc(x: String, y: String)(g: Int => Int => Int) = g(x.toInt)(y.toInt)
def hunc(x: String, y: String)(h: Tuple2[Int, Int] => Int) = h((x.toInt, y.toInt))
}
[ADD COMMENT]
I wonder...
We can declare as "implicit x => ..." with one arg.
It seems there is no way to declare two implicit args.
Try adding:
val c = hunc("2", "4") { implicit pair => pair._1 * pair._2 }
When you say implicit y => y * 2 you're not
declaring an implicit argument but mark the function as implicit,
so you make an analog to this:
implicit val f1 = (y: Int) => y * 2
def func1(x: String, y: String)(f: Int => Int) = f(1)
func1("", "")(f1)
When you want to mark a function with two
arguments as implicit you can do it this way:
implicit val f2 = (x: Int, y: Int) => y * 2
def func2(x: String, y: String)(f: (Int, Int) => Int) = f(1, 2)
func2("", "")(f2)
But you cannot do it so:
func2("", "")(implicit (x, y) => x), in this particular case I just don't see any meaning to use implicits.
Also you can see this question, maybe you'll find some useful information there
I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.
def foo(a:Int, b:Int) = {}
foo(a,b) //right way to invoke foo
foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??
def getParams = {
//Some calculations
(a,b) //where a & b are Int
}
It's a two step procedure. First turn foo into a function, then call tupled on it to make it a function of a tuple.
(foo _).tupled(getParams)
#dave-griffith is dead on.
You can also call:
Function.tupled(foo _)
If you want to wander into "way more information than I asked for" territory, there are also methods built into partially applied functions (and on Function) for currying. A few input/output examples:
scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double
scala> foo _
res0: (Int, Double) => Double = <function2>
scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>
scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>
scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>
// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>
Wherein the curried version is invoked with multiple argument lists:
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> c(5)
res13: (Double) => Double = <function1>
scala> c(5)(10)
res14: Double = 50.0
Finally, you can also uncurry/untuple if needed. Function has builtins for this:
scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>
scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Function.tupled(foo _)(getParams) or the one suggested by Dave.
EDIT:
To respond to your comment:
What if foo happens to be the
constructor of some class?
In that case, this trick won't work.
You can write a factory method in the companion object of your class and then obtain the tupled version of its apply method using one of the aforementioned techniques.
scala> class Person(firstName: String, lastName: String) {
| override def toString = firstName + " " + lastName
| }
defined class Person
scala> object Person {
| def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
| }
defined module Person
scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G
With case classes you get a companion object with an apply method for free, and thus this technique is more convenient to use with case classes.
scala> case class Person(firstName: String, lastName: String)
defined class Person
scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)
I know that's a lot of code duplication but alas... we don't have macros (yet)! ;)
I appreciate some of the other answers which were closer to what you asked for, but I found it easier for a current project to add another function which converts tuple parameters into the split parameters:
def originalFunc(a: A, b: B): C = ...
def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
Now, you can implement foo and make it take a param of the Tuple2 class like so.
def foo(t: Tuple2[Int, Int]) = {
println("Hello " + t._1 + t._2)
"Makes no sense but ok!"
}
def getParams = {
//Some calculations
val a = 1;
val b = 2;
(a, b) //where a & b are Int
}
// So you can do this!
foo(getParams)
// With that said, you can also do this!
foo(1, 3)