转换由名称参数

转换由名称参数

问题描述:

我想创建一个函数与下面的签名元组:转换由名称参数

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的预期效果?
+1

为什么一个元组,什么是错的2个参数? –

+1

@ insan-e实际上会有myFunction的多种变体。它可以称为'myFun(“a” - > 1 * 2,“b” - > 3 * 4)“或myFun(”a“ - > 1 * 2,”b“ - > 3 * 4” c“ - > 5 * 6)'等等。因为可能有很多参数,所以我想避免任何不必要的语法来保持它的可读性。 – Mifeet

+1

我明白了。你不能这样做,可能是因为[元组](https://github.com/scala/scala/blob/v2.12.3/src/library/scala/Tuple2.scala#L19)有热烈的争论。我看到的唯一方法是按名称创建整个元组,'functionWithName:=>(String,T)'... –

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

  • 制作整个元组通过名字: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(见ArrowAssocPredef):

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 
+0

是的,那是另一种选择。但是,如果没有不必要的2个括号和箭头运算符,怎么办?任何想法为什么隐式转换不起作用? – Mifeet

+0

@Mifeet查看我更新的答案。如果你提供这个类型,'implicit'就起作用。 – adrice727