传递scala中的默认参数?

时间:2012-08-09 01:56:51

标签: scala default-parameters

请考虑以下示例

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?

2 个答案:

答案 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]来调用该函数。