使用名称参数转换为元组

Conversion to tuple with by-name parameter

我想创建一个具有以下签名的函数:

def myFunction[T](functionWithName: (String, => T)): T 

这样我就可以调用它,例如:val x = myFunction("abc" -> 4 * 3)。然而,元组不接受按名称的参数,因此上面的签名无效。

受到this answer的启发,我尝试了以下隐式转换:

implicit class ByName[T](getValue: => T) extends Proxy {
  def apply(): T = getValue
  def self = apply()
}

def myFunction[T](functionWithName: (String, ByName[T])): T = {
  // do something
  functionWithName._2()
}

然而,隐式在这种情况下不起作用(与链接的答案不同)。

您可以将 call-by-name 参数更改为 thunk。

def myFunction[T](functionWithName: (String,() => T)): T = functionWithName._2()

myFunction(("abc", () => 4 * 3)) // 12

或者要让它与 implicit 一起工作,您只需要明确地提供类型 myFunction :

myFunction[Int]("abc" -> 4 * 3) // 12

我有两个实施方案:

  • 为整个元组命名:functionWithName: => (String, T)

  • 自己制作class:

    class MyTuple[A, B](a: A, b: => B) {
      def _1: A = a
      def _2: B = b
      def toTuple = a -> b // optional
    }
    

并且在某处有一个自定义的隐式方法,比如 -> for Tuple2(参见 Predef 中的 ArrowAssoc):

  implicit final class ArrAssoc[A](private val self: A) extends AnyVal {
    @inline def -->[B](y: => B): MyTuple[A, B] = {
      new MyTuple(self, y)
    }
  }

那你可以这样说:

  val t = 1 --> { println("blah"); 5 }
  //t._2
  //t.toTuple

在您调用 t._2 之前,不应计算 b 参数 甚至进行 toTuple 隐式转换,因此当 Tuple2 被尊重时,您可以传递 MyTuple...