请考虑以下示例
def foo(a: Int, b: Int = 100) = a + b
def bar(a: Int, b: Int = 100) = foo(a, b) * 2
这样可行,但请注意,我必须在两个函数中为b提供相同的默认值。我的意图实际上是以下
def bar(a: Int, b: Int) = foo(a, b) * 2
def bar(a: Int) = foo(a) * 2
但是当你有更多的可选参数和链中的其他函数(例如以相同方式调用bar的baz)时,这会变得很麻烦。有没有更简洁的方法来表达scala?
答案 0 :(得分:4)
我不认为有;如果你用一个加倍函数组成foo:
val bar = (foo _).curried((_: Int)) andThen ((_: Int) *2)
// (please, please let there be a simpler way to do this...)
你丢失了默认参数,因为函数对象don't have them。
如果在您的用例中值得,您可以创建一个包含您传递的参数的案例类,而不是多个单独的参数,例如。
case class Args(a: Int, b: Int = 100, c: Int = 42, d: Int = 69)
def foo(args: Args) = { import args._; a + b + c + d }
def bar(args: Args) = foo(args) * 2
答案 1 :(得分:2)
我建议使用Option
。
def bar(a: Int, b: Option[Int] = None) = b match {
case Some(x) => foo(a,x) * 2
case _ => foo(a) * 2
}
这将完全符合您的要求。另一种方法是使用varargs。
def baz(a: Int)(b: Int*) = b.headOption match {
case Some(x) => foo(a,x) * 2
case _ => foo(a) * 2
}
我更喜欢第一种方式,因为很明显,参数是可选的。第二个解决方案不是处理Option
中的包装,但签名不清楚只会考虑集合的第一个元素。 baz(1)(2) == baz(1)(2,3,4,5)
是真的。
修改强>
要使Option
看起来像您想要的电话,您可能会使用隐含。
implicit def int2Some(i: Int) = Some(i)
现在您可以调用以下函数:
bar(1,2)
bar(1,Some(2))
bar(1)
bar(1,None)
implicit
会自动调用,只要它有用。但是您的用户可能会感到困惑,为什么可以使用Int
而不是Option[Int]
来调用该函数。