我在scala中有一个返回元组的函数:
private def someFunction(from: List[Any], to: List[Any]): (List[Any], List[Any]) = {
// Do some stuff
(modifiedFrom, modifiedTo)
}
我想分解该元组,并将值作为参数传递给另一个函数:
@tailrec
someOtherFunction(first: List[Any], second: List[Any], third: List[Any]): Unit = {
// Some more stuff
val (two, three) = someFunction(foo, bar)
someOtherFunction(one, two, three)
}
是否可以改写:
someOtherFunction(one, someFunction(foo,bar)) // This is a compile error.
我能以更干净的方式编写分解吗?
答案 0 :(得分:3)
不太漂亮(scala想要类型归属),但如果你真的想要单行:
def f1(): (Int, Int) = (2,3)
def f2(a: Int, b: Int, c: Int) = 0
(f2(1, _: Int, _: Int)).tupled(f1())
说明:
tupled
是为每个Function
实例定义的方法(作为一等公民lambda)。它返回一个可以接受元组的函数。
f2(1, _: Int, _: Int)
是一个部分应用程序 - 它在这里从第二个和第三个参数返回一个函数,所以之后它可以被“tupled”
P.S。您可以通过将f2
重新定义为:
def f2(a: Int)(b: Int, c: Int) = 0
f2(1) _ tupled f1()
更新。如果您不想打破尾递归,请使用TailCalls:
import scala.util.control.TailCalls._
def f2(a: Int)(b: Int, c: Int): TailRec[Int] =
if (false) tailcall(f2(1) _ tupled f1()) else done(0)
f2(1)(2, 3).result
此处的另一个好处是,如果f2
变得更复杂 - 在代码中跟踪尾部调用会更容易。它还支持相互尾递归等功能。
说明:
tailcall
标记了一个尾递归调用done
标记您希望在循环结束时返回的值.result
运行堆栈安全计算并从TailCall[T]
中提取结果。您还可以注意到TailCall
包装器向@tailrec
播放simillar角色 - 它不允许非尾部定位调用,因为它需要“解包”结果。编译器级优化正在被蹦床计算所取代,这也是堆栈安全的。答案 1 :(得分:2)
我认为没有更清洁的方法。也许有可能使用宏来做某事,但它有点挫败了目的。
只有我能想到的替代品(有点清洁,因为它不会污染命名空间)如下:
REST
答案 2 :(得分:2)
如果使用两个参数组定义了someOtherFunction
,那么它很容易。
而不是......
val (two, three) = someFunction(foo, bar)
someOtherFunction(one)(two, three)
......你可以这样做。
someOtherFunction(one) _ tupled someFunction(foo, bar)
但是,你可能不得不将元组分解为其部分。