【问题标题】:Conversion to tuple with by-name parameter使用按名称参数转换为元组
【发布时间】:2018-03-30 13:50:53
【问题描述】:

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

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

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

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 是按名称传递的?

【问题讨论】:

  • 为什么是元组,2个参数有什么问题?
  • @insan-e 实际上会有多个 myFunction 变体。它可以被称为myFun("a" -> 1*2, "b" -> 3*4)myFun("a" -> 1*2, "b" -> 3*4, "c" -> 5*6) 等。因为可能有很多参数,我想避免任何不必要的语法以保持可读性。
  • 我明白了。你不能这样做可能是因为tuples 有急切的论据。我看到的唯一方法是按名称制作整个元组,functionWithName: => (String, T)...
  • 我喜欢这样,一个优雅的解决我的问题。它不能在所有情况下使用(例如,当需要在 T 之前评估 String 时),但可以在其他情况下使用。如果这是一个答案,会投票赞成。

标签: scala implicit-conversion callbyname


【解决方案1】:

您可以将 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 个括号和箭头运算符?任何想法为什么隐式转换不起作用?
  • @Mifeet 查看我的更新答案。如果您提供类型,implicit 将起作用。
【解决方案2】:

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

  • 按名称制作整个元组: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(参见 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...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    • 2022-11-09
    相关资源
    最近更新 更多