【问题标题】:passing on default parameter in scala?在scala中传递默认参数?
【发布时间】:2012-08-06 05:23:36
【问题描述】:

请考虑以下示例

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

【问题讨论】:

  • 请把你的问题说清楚:你觉得这里有什么麻烦?你到底在找什么?如果你正在寻找一种更简洁的方式来编写默认参数,那就没有了,怎么可能呢?

标签: scala default-parameters


【解决方案1】:

我认为没有;如果你用加倍函数组成 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

【讨论】:

  • 技术太棒了。每次遇到重载方法时都应该由编译器自己完成:将其转换为关联的数据类和函数。函数比方法更便于操作。
  • 是的,我想案例类解决方案是你能做的最好的。感觉虽然这可能是一个有用的功能,可以在 scala 编译器中轻松实现。我想到的是这样的: def bar(a: Int, b: Int = _) = foo(a, b) * 2, scala 可以检查 b 仅用于已定义默认值的地方,因此它可以毫不含糊地解释这一点。
【解决方案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
}

我更喜欢第一种方式,因为很明显,参数是可选的。第二种解决方案是不处理 Option 中的包装,但签名并不清楚,只考虑集合的第一个元素。 baz(1)(2) == baz(1)(2,3,4,5) 是真的。

编辑

要使带有Option 的调用看起来像您想要的调用,您可以使用implicits。

implicit def int2Some(i: Int) = Some(i)

现在您可以调用以下函数:

bar(1,2)
bar(1,Some(2))
bar(1)
bar(1,None)

implicit 会在有用的地方自动调用。但是您的用户可能会感到困惑,为什么可以使用 Int 而不是 Option[Int] 来调用该函数。

【讨论】:

  • 第一个解决方案不允许您调用 bar(1)。你必须说 bar(1, None)。另外,以前是 bar(1, 2) 现在需要写成 bar(1, Some(2))。使用重复参数更接近所需的语法,但我想如果你有两个或更多可选参数,它就行不通了?是的,它也有你提到的问题。
  • 您可以通过将第一个问题设为默认值来解决第一个问题。我添加了那个。
  • 第二个问题可以通过使用隐式来解决。我也加了那个。
  • 是的,通过修复,您的解决方案可以实现我想要的确切语法。但是,实现这个看似简单的功能对我来说是太多的代码。考虑一下你有更多可选参数的情况,你最终会得到尽可能多的匹配语句,并且必须在每个想要传递默认值的函数中重复它们。这是很多样板,恕我直言,这正是 Scala 试图避免的类型。另一个小问题是 int2some 默认值似乎有点危险。但感谢您完成这项工作。我的抱怨主要是针对 Scala 编译器。
猜你喜欢
  • 2016-01-02
  • 2014-04-09
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 2016-12-14
相关资源
最近更新 更多