我可以:
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)
^
还有其他方法可以做我想要的吗?为什么不允许这样做?
答案 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