1

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

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

这样我就可以这样称呼它,例如:val x = myFunction("abc" -> 4 * 3). 但是,Tuple 不接受 by-name 参数,因此上面的签名是无效的。

这个答案的启发,我尝试了以下隐式转换:

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

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

  • 为什么隐式转换ByName不起作用?
  • 如何实现调用myFunction("abc" -> 4 * 3)where 4 * 3is pass by name 的预期效果?
4

2 回答 2

4

您可以将 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
于 2017-10-18T16:22:16.790 回答
1

我有两个建议来实现这一点:

  • 按名称制作整个元组:functionWithName: => (String, T)

  • 制作自己的课程:

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

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

  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

在您调用或什至进行隐式转换b之前,不应评估该参数,因此当您考虑时,您可以传递一个...t._2toTupleTuple2MyTuple

于 2017-10-21T09:55:59.743 回答