【问题标题】:How to pass a tuple argument the best way?如何以最佳方式传递元组参数?
【发布时间】:2012-08-27 04:16:08
【问题描述】:

如何以最佳方式传递元组参数?

例子:

def foo(...): (Int, Int) = ...

def bar(a: Int, b: Int) = ...

现在我想将foo 的输出传递给bar。这可以通过以下方式实现:

val fooResult = foo(...)
bar(fooResult._1, fooResult._2)

这种方法看起来有点难看,尤其是当我们处理带有n > 2n-tuple 时。此外,我们必须将 foo 的结果存储在一个额外的值中,否则foo 必须使用bar(foo._1, foo._2) 执行多次。

有没有更好的方法将元组作为参数传递?

【问题讨论】:

标签: scala arguments tuples


【解决方案1】:

每个函数都有一个特殊的tupled 方法:

val bar2 = (bar _).tupled  // or Function.tupled(bar _)

bar2 接受(Int, Int) 的元组(与bar 参数相同)。现在你可以说:

bar2(foo())

如果您的方法实际上是函数(注意 val 关键字),那么语法会更令人愉悦:

val bar = (a: Int, b: Int) => //...
bar.tupled(foo())

另见

【讨论】:

  • 谢谢,这就是我要找的。这对我有用。额外问题:您提到方法和函数之间存在区别-有什么区别?我想了解更多。你能给我一些参考资料/链接吗?
  • @JohnThreepwood:Scala 中的方法转换为 Java 中的方法。 Scala 中的函数转换为对象。在 Scala 中,这主要是透明的(搜索“eta-expansion”),但有时语法略有不同。 This article很全面。
  • 令人失望的是,这仅适用于方法,当然令人不快的是 scala 为其 api 提供了如此多毛的表面。绕过这些语言限制没有什么能让我们变得更聪明也更高效......
【解决方案2】:

正如@Tomasz 所提到的,使用tupled 是一个好方法。

您还可以在赋值期间提取从foo 返回的元组:

val (x, y) = foo(5)
bar(x, y)

这有利于代码更简洁(没有_1_2),并允许您为xy 分配描述性名称,使您的代码更易于阅读。

【讨论】:

  • 谢谢。我同意,这更具可读性。我会记住这个技巧。但是额外的价值让我有点恼火。我想通过它而不将结果保存为额外的值。但仍然感谢您的提示!
【解决方案3】:

也值得了解

foo(...) match { case (a,b) => bar(a,b) }

作为不需要您显式创建临时fooResult 的替代方案。当速度和不混乱都很重要时,这是一个很好的折衷方案。您可以使用bar _ 创建一个函数,然后将其转换为使用.tupled 的单个元组参数,但是每次调用该对时都会创建两个新的函数对象;您可以存储结果,但这可能会使您的代码不必要地混乱。

对于日常使用(即这不是代码的性能限制部分),您可以

(bar _).tupled(foo(...))

排队。当然,您创建了两个额外的函数对象,但您很可能也刚刚创建了元组,所以您不太关心,对吧?

【讨论】:

  • 感谢您指出这个替代方案。但是为什么作为返回值的元组是不关心性能的标志呢?但是,是的,你是对的,在我的程序中,性能并不重要。
  • @JohnThreepwood - 您必须创建一个对象才能返回一个元组。如果与创建对象相比,您所做的任何事情都比较昂贵,那么与创建两个对象相比(这就是您使用bar _.tupled 得到的),它可能也很昂贵。如果与创建对象相比,您所做的事情很便宜,那么您为什么要创建对象?你应该传入一个带有你可以设置的变量的对象。 (后一种方法是你应该很少做的事情——对象创建相当便宜。)
  • 感谢您的澄清。解释有道理,我会记住的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
  • 2021-03-17
  • 2014-03-01
  • 2019-04-22
  • 2011-10-18
  • 1970-01-01
  • 2016-06-14
相关资源
最近更新 更多