kevinykuo
kevinykuo

Reputation: 4762

Returning a function using another function via pattern matching

I'm trying to write a function that returns another function based on a string input. I think I want matchfun("X") to be a (Double, Double) => Double:

def matchfun(foo: String) = {
    foo match {
        case "X" => (x: Double, y: Double) => x + y
        case "Y" => (x: Double) => x + 2
        case "Z" => (x: Double, y: Double) => x * y
    }
}
matchfun("X")
matchfun("X")(1,2)
matchfun: (foo: String)Object
res116: Object = <function2>
<console>:173: error: Object does not take parameters
       matchfun("X")(1,2)
                    ^

Upvotes: 0

Views: 82

Answers (4)

caeus
caeus

Reputation: 3696

Your problem is that you have to help the compiler, and all the branches in the "match" statement should return the same type. You break those constraints in the second case "Y", because you return a function Double=>Double and not a function (Double,Double)=>Double.

Help the compiler

def matchfun(foo: String):(Double,Double)=>Double = {
  foo match{
  case "X"=> (a,b)=> a+b
  case "Y"=> (a,b)=> a+2
  case "Z"=> (a,b)=> a*b
  }
}

Upvotes: 0

Sumeet Sharma
Sumeet Sharma

Reputation: 2583

Try this:

trait A extends ((Int,Int) => Int) with (Int => Int)

class B extends A {
   def apply(a: Int, b: Int) = a + b
   def apply(a: Int) = a
}

val b = new B

b(1) // 1
b(2,3) // 5

Read about function type inheritance.

EDIT

to handle the case mentioned in the comment:

trait A extends ((Int,Int,String) => Int) with (Int => Int)

class B extends A {

  override def apply(a:Int,b:Int,x:String) = x match {
         case "add" => a+b
         case "mul" => a*b
  }
  override def apply(x:Int) = x
}

val b = new B
b(1) // 1
b(1,2,"add") // 3
b(1,2,"mul") // 2

Upvotes: 0

Oleksandr.Bezhan
Oleksandr.Bezhan

Reputation: 2168

You return functions that accept different inputs, so it's hard to push the input without knowing what parameters are needed. So instead of pushing the input, let the function pull the input on its own.

So we need some sort of source object, let's call it Point:

case class Point(x: Double, y: Double)

def matchfun(foo: String)(point: Point) = {
  foo match {
    case "X" => point.x + point.y
    case "Y" => point.x + 2
    case "Z" => point.x * point.y
  }
}

val point = Point(2, 5)
matchfun("X")(point) // 7.0
matchfun("Y")(point) // 4.0
matchfun("Z")(point) // 10.0

Upvotes: 0

puhlen
puhlen

Reputation: 8519

When foo is "X" your return a Function2[Double,Double,Double] when foo is "Y" you return a Function1[Double,Double] Object (anyref) is the most specific common supertype available. Change your code so that all branches return the same type (or at least a useful common supertype). In the case of returning functions that means you need to have the same number of parameters for each function.

Upvotes: 1

Related Questions