【问题标题】:Scala: Unpacking tuple as part of argument listScala:将元组解包为参数列表的一部分
【发布时间】:2014-08-03 12:17:06
【问题描述】:

我正在尝试发送方法调用元组的结果,作为另一个方法的参数列表的部分

目标方法

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

【问题讨论】:

    标签: scala tuples iterable-unpacking arity


    【解决方案1】:

    您可以执行以下操作:

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

    【讨论】:

    • 谢谢,我同意这行得通。但是我可以在不解包元组的情况下做到这一点吗?
    • 嗯,这与您最初提出的问题不同:“更优雅的解包方式”。 :-) 现在你想在不拆包的情况下做到这一点。
    • 我认为我表达的问题不够清楚:) 不过我赞成。我想做类似invokeMethod(arg1, arg2, tuple)
    • 当然,如果你能改变或重载 def printResult(title: String, result: Int, startTime: Long, endTime: Long) 的方法签名为 def printResult(title: String, t : [Int, Long, Long]) 你不必在调用 printResult 之前解压元组。
    【解决方案2】:

    一种方法涉及元组的案例类,例如这样,

    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)
    

    【讨论】:

    • 感谢您的建议。是的,案例类和类型定义是可能的。我正在寻找简洁而富有表现力的东西。例如。 Python 的 kwargs
    • @hanxue kwargs 方法可能会在假设元组中的所有元素都属于同一类型的情况下起作用;但是考虑 (1,2,3).productIterator 的类型是 Iterator[Any] 虽然我们知道所有元素都是 Int.
    【解决方案3】:

    你是否附上了这个函数签名?

    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))
    

    【讨论】:

      【解决方案4】:

      这确实可以在不使用 shapeless 解包元组的情况下实现(并像你一样对函数进行元组):

      import shapeless.syntax.std.tuple._
      
      (printResult _).tupled("Hi" +: sendAndReceive(???))
      

      "Hi" +: sendAndReceive(???) 只是将值 "Hi" 添加到 sendAndReceive 返回的元组之前。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多