3

请考虑以下示例

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中表达这一点?

4

2 回答 2

4

我认为没有;如果你用加倍函数组成 foo :

val bar = (foo _).curried((_: Int)) andThen ((_: Int) *2)
// (please, please let there be a simpler way to do this...)

您会丢失默认参数,因为函数对象没有它们

如果在您的用例中值得,您可以创建一个包含您传递的参数的案例类,而不是多个单独的,例如

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
于 2012-08-09T04:02:00.753 回答
2

我建议使用Option.

def bar(a: Int, b: Option[Int] = None) = b match {
  case Some(x) => foo(a,x) * 2
  case _ => foo(a) * 2
}

这将完全满足您的需求。另一种方法是使用可变参数。

def baz(a: Int)(b: Int*) = b.headOption match {
  case Some(x) => foo(a,x) * 2
  case _ => foo(a) * 2
}

我更喜欢第一种方式,因为很明显,参数是可选的。第二种解决方案是不处理 an 中的包装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就会自动调用。但是您的用户可能会感到困惑,为什么可以使用 anInt而不是Option[Int].

于 2012-08-09T06:07:01.857 回答