带有惰性“by-name”参数的参数列表(“*”)?

时间:2013-05-01 14:15:40

标签: scala optional-parameters callbyname

我可以:

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)
                ^

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

1 个答案:

答案 0 :(得分:6)

此处=>表示参数按名称传递。您尝试过的内容并不是因为=>String不是实际类型(而不是()=>String)而且您无法创建Array[=>String]。假设变量参数x: T*作为包含所有参数值的数组(如x: Array[T])处理,这就是为什么无法创建{{{ 1}}(这没有意义)也意味着变量参数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来获取actal值:

apply

鉴于def foo( fs: ByName[String]* ) = fs foreach { f => println( f() ) } 扩展ByName用于简单的事情,例如致电Proxy或测试平等,您甚至不必致电toString。因此,你可以简单地做:

apply