Scala:将元组作为参数列表的一部分进行解包

17

我正在尝试将一个方法调用返回的元组作为另一个方法参数列表中的一部分发送。

目标方法

def printResult(title: String, result: Int, startTime: Long, endTime: Long)

从方法返回,部分参数列表

def sendAndReceive(send: Array[Byte]): (Int, Long, Long)
换句话说,我试图调用printResult(String, (Int, Long, Long))。如果方法的返回签名与方法调用匹配,那么我可以使用。
(printResult _).tupled(sendAndReceive(heartbeat))

这会导致语法错误

printresult("Hi", Function.tupled(sendAndReceive(heartbeat))

解决方法

我采用手动解包元组的方式,在调用该方法时使用。

val tuple = sendAndReceive(heartbeat)
printResult("Heartbeat only", tuple._1, tuple._2, tuple._3)

有没有更优雅的方式来解包并将元组作为参数列表的一部分发送?

参考资料

Scala: Decomposing tuples in function arguments

Invoke a method using a tuple as the parameter list

Will tuple unpacking be directly supported in parameter lists in Scala?

Tuple Unpacking in Map Operations

4个回答

23

您可以进行以下操作:

val (result, startTime, endTime) = sendAndReceive(heartbeat)
printResult("Heartbeat only", result, startTime, endTime)

5
谢谢,我同意这个方法可行。但是我能否在不解包元组的情况下进行操作? - Hanxue
那是一个与您最初提出的问题不同的问题:“更优雅的拆包方式”。现在您想在不拆包的情况下进行。 - Carl
1
我觉得我没有表达清楚问题 :) 尽管如此,我还是点了赞。我想做类似于 invokeMethod(arg1, arg2, tuple) 这样的事情。 - Hanxue
当然,如果您可以更改或重载def printResult(title:String,result:Int,startTime:Long,endTime:Long)的方法签名为def printResult(title:String,t:[Int,Long,Long]),则在调用printResult之前不必解包元组。 - Carl

5
你是否依赖于这个函数签名?
def printResult(title: String, result: Int, startTime: Long, endTime: Long)

如果这是您自己的代码并且您可以修改它,那么您可以尝试使用柯里化来实现,就像这样:

如果是你的代码,而且你能够修改它,那么你可以尝试使用柯里化,像这样:

def printResult(title: String)(result: Int, startTime: Long, endTime: Long)

那么你可以这样执行它:
printResult("Curried functions!") _ tupled(sendAndReceive(heartbeat))

1
一种方法是使用 case 类来表示元组,例如像这样:
case class Result(result: Int, startTime: Long, endTime: Long) {
  override def toString() = s"$result ($startTime to $endTime)"
}

def sendAndReceive(send: Array[Byte]): Result = {
  // body
  Result(1,2,3)
}

def printResult(title: String, res: Result) = println(title + res)

1
谢谢您的建议。是的,可以使用case class和类型定义。我正在寻找简洁而富有表现力的东西。例如Python的kwargs。 - Hanxue
@hanxue 如果元组中的所有元素属于相同类型,则kwargs方法可能有效;但是考虑(1,2,3)的类型。productIterator是Iterator[Any],尽管我们事先知道所有元素都是Int。 - elm

1

不需要使用shapeless解包元组(并像您所做的那样对函数进行元组化),也可以实现此操作:

import shapeless.syntax.std.tuple._

(printResult _).tupled("Hi" +: sendAndReceive(???))

"Hi" +: sendAndReceive(???) 只是在 sendAndReceive 返回的元组前面添加了值为 "Hi" 的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接