2

我可以:

scala> def foo( f: => String) = println(f)
foo: (f: => String)Unit

我可以:

scala> def foo( f: String*) = f.map(println)
foo: (f: String*)Seq[Unit]

但我不能:

scala> def foo( f: =>String* ) = f.map(println)
<console>:1: error: ')' expected but identifier found.
       def foo( f: =>String* ) = f.map(println)
                       ^

也不

scala> def foo( f: (=>String)* ) = f.map(println)
<console>:1: error: no by-name parameter type allowed here
       def foo( f: (=>String)* ) = f.map(println)
                ^

还有其他方法可以做我想做的事吗?为什么不允许这样做?

4

1 回答 1

6

这里的=>意思是参数是按名称传递的。不允许您尝试的只是因为=>String它不是实际类型(而不是 say ()=>String)并且您不能制作Array[=>String]. 鉴于可变参数x: T*在后台处理为包含所有参数值的数组(如 中x: Array[T]),这就是为什么无法创建 a Array[=>String](这没有意义)也意味着可变参数f: (=>String)*是不可能的.

这个问题可以使用一个小的包装类来解决:

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

然后像这样更改方法的签名:

def foo( fs: ByName[String]* )

当使用多个参数调用您的方法时,所有参数将被隐式包装到一个ByName实例中,然后您可以调用apply以获取实际值:

def foo( fs: ByName[String]* ) = fs foreach { f => println( f() ) }

鉴于它可以ByName扩展Proxy简单的事情,例如调用toString或测试相等性,您甚至不必调用apply. 因此,您可以简单地执行以下操作:

def foo( fs: ByName[String]* ) = f foreach println
于 2013-05-01T14:33:31.360 回答