通过模式匹配使用另一个函数返回函数

时间:2017-05-12 19:51:41

标签: scala

我试图编写一个基于字符串输入返回另一个函数的函数。我想我希望matchfun("X")成为(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)
                    ^

4 个答案:

答案 0 :(得分:1)

当foo是&#34; X&#34;当foo为&#34; Y&#34;时,您返回Function2[Double,Double,Double]返回Function1[Double,Double]对象(anyref)是可用的最具体的常用超类型。更改您的代码,以便所有分支返回相同的类型(或至少是一个有用的常用超类型)。在返回函数的情况下,这意味着每个函数需要具有相同数量的参数。

答案 1 :(得分:0)

试试这个:

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

阅读有关函数类型继承的内容。

修改

处理评论中提到的案例:

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

答案 2 :(得分:0)

您返回接受不同输入的函数,因此在不知道需要哪些参数的情况下很难推送输入。因此,不要按下输入,而是让函数自行提取输入。

所以我们需要某种源对象,我们称之为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

答案 3 :(得分:0)

您的问题是您必须帮助编译器,并且“match”语句中的所有分支应返回相同的类型。您在第二种情况“Y”中破坏了这些约束,因为您返回的是函数Double=>Double而不是函数(Double,Double)=>Double

帮助编译器

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
  }
}