在Scala中,如何定义一个带有元组参数的函数变量

时间:2015-10-06 20:05:40

标签: scala tuples

在Scala类中,目标是实现Builder模式,构造类的一个参数是一个接受元组并返回Double的函数。

在Builder类中,需要变量tupleFunc来保存具有默认实现的此类型的函数。 Builder还将使用方法tupleFuncIs来覆盖默认值。

class FunctionProblem private (val tupleFunc: (Boolean, Double, Int) => Double,
                               val func: Double => Double) {

}

object FunctionProblem {
  class Builder {
    // problem line follows
    private var tupleFunc: ((Boolean, Double, Int) => Double) = (x: (Boolean, Double, Int)) => if (x._1) x._2 else x._3.toDouble
    private var func: (Double => Double) = (x: Double) => 0.75 * x

    def tupleFuncIs(x: (Boolean, Double, Int) => Double): Builder = { tupleFunc = x; this }
    def funcIs(x: Double => Double): Builder = { func = x; this }

    def build(): FunctionProblem = new FunctionProblem(tupleFunc, func)
  }

  def builder(): Builder = new Builder
}

但是,Scala编译器抱怨类型不匹配

[ant:scalac]  found   : ((Boolean, Double, Int)) => Double
[ant:scalac]  required: (Boolean, Double, Int) => Double
[ant:scalac]     private var tupleFunc: ((Boolean, Double, Int) => Double) = (x: (Boolean, Double, Int)) => if (x._1) x._2 else x._3.toDouble
[ant:scalac]                                                                                             ^

为什么找到双括号,或者更好的是,如何重写tupleFunc以满足编译器的需要?

1 个答案:

答案 0 :(得分:3)

你需要更多的支持

class FunctionProblem private (val tupleFunc: ((Boolean, Double, Int)) => Double,
  val func: Double => Double) {

}

object FunctionProblem {
  class Builder {
    // problem line follows
    private var tupleFunc: ((Boolean, Double, Int)) => Double = (x: (Boolean, Double, Int)) => if (x._1) x._2 else x._3.toDouble
    private var func: (Double => Double) = (x: Double) => 0.75 * x

    def tupleFuncIs(x: ((Boolean, Double, Int)) => Double): Builder = { tupleFunc = x; this }
    def funcIs(x: Double => Double): Builder = { func = x; this }

    def build(): FunctionProblem = new FunctionProblem(tupleFunc, func)
  }

  def builder(): Builder = new Builder
}

你的类型

((Boolean, Double, Int) => Double)

只是一个函数,它接受3个参数而不是元组,对于元组,你需要将它包装在另一个()中,如下所示:

(((Boolean, Double, Int)) => Double)

顺便说一下,尽管你的代码中的函数功能不是很强大,但它看起来很像java。您应该考虑使用不可变值并在中间化时返回新构建器。

我建议以更加scala的方式实现此任务是使用case class

import FunctionProblem._

case class FunctionProblem(tupleFunc: TupleFunc = defaultTupleFunc, func: DoubleFunc = defaultDoubleFunc)

object FunctionProblem {
  type TupleFunc = ((Boolean, Double, Int)) => Double
  type DoubleFunc = Double => Double

  private val defaultTupleFunc: TupleFunc = x => if (x._1) x._2 else x._3.toDouble
  private val defaultDoubleFunc: DoubleFunc = 0.75 * _
}

FunctionProblem().func(3) //res0: Double = 2.25
FunctionProblem(func = _ + 5).func(3) //res1: Double = 8.0
FunctionProblem(tupleFunc = _ => 32).tupleFunc((true, 5, 1)) //res2: Double = 32.0   

如果您想进行连锁电话,可以使用自动生成的copy方法

FunctionProblem().copy(func = _ + 9).copy(tupleFunc = _ => 3).func(1) //res3: Double = 10.0