转换由名称参数
问题描述:
我想创建一个函数与下面的签名元组:转换由名称参数
def myFunction[T](functionWithName: (String, => T)): T
,这样我可以调用它,例如,像这样:val x = myFunction("abc" -> 4 * 3)
。但是,Tuple不接受名称参数,所以上面的签名是无效的。
通过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()
}
隐含不会在这种情况下工作,但是(不像在链接的答案)。
- 为什么隐式转换为
ByName
不起作用? - 如何才能达到
myFunction("abc" -> 4 * 3)
的名称所要传递4 * 3
的预期效果?
答
我有两个建议,以实现这一点:
制作整个元组通过名字:
functionWithName: => (String, T)
-
使自己的等级:
class MyTuple[A, B](a: A, b: => B) { def _1: A = a def _2: B = b def toTuple = a -> b // optional }
,并有一个自定义的隐式方法的地方,像->
用于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
The b
para仪表不应该被评估,直到调用t._2
甚至使toTuple
imlicit转换,所以当Tuple2
被espected你可以传递一个MyTuple
...
答
您可以将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
为什么一个元组,什么是错的2个参数? –
@ insan-e实际上会有myFunction的多种变体。它可以称为'myFun(“a” - > 1 * 2,“b” - > 3 * 4)“或myFun(”a“ - > 1 * 2,”b“ - > 3 * 4” c“ - > 5 * 6)'等等。因为可能有很多参数,所以我想避免任何不必要的语法来保持它的可读性。 – Mifeet
我明白了。你不能这样做,可能是因为[元组](https://github.com/scala/scala/blob/v2.12.3/src/library/scala/Tuple2.scala#L19)有热烈的争论。我看到的唯一方法是按名称创建整个元组,'functionWithName:=>(String,T)'... –