本文介绍了带有懒惰的“按名称"的参数列表("*")参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以:

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

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

Is there some other way to do what I want? Why isn't this allowed?

推荐答案

此处=>表示参数是通过名称传递的.仅仅因为=>String不是实际类型(而不是()=>String)并且您不能创建Array[=>String],所以您尝试过的内容是不允许的.假设可变参数x: T*作为包含所有参数值的数组处理(如x: Array[T]中),这就是为什么无法创建Array[=>String]的原因(这没有意义)也意味着可变参数f: (=>String)*是不可能的.

Here the => means that the parameter is passed by name. What you have tried isn't allowed simply because =>String is not an actual type (as opposed to say ()=>String) and you cannot make an Array[=>String]. Given that a variadic parameter x: T* is under the hood handled as an array containing all the parameter's values (as in x: Array[T]), this is the reason why not being able to create a Array[=>String] (which does not make sense) also means that a variadic parameter f: (=>String)* is not possible.

可以使用一些包装器类来解决此问题:

This problem can be worked around using a little wrapper class:

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

然后按如下所示更改方法的签名:

Then change the signature of your method like so:

def foo( fs: ByName[String]* )

在调用带有多个参数的方法时,所有参数都将隐式包装到ByName实例中,然后可以调用apply来获取实际值:

When calling your method with multiple arguments, all the arguments will be implicitly wrapped into a ByName instance, and then you can call apply to get the actal value:

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

考虑到ByName扩展了Proxy的功能,例如调用toString或测试相等性,您甚至不必调用apply.因此,您可以简单地执行以下操作:

Given that ByName extends Proxy for simple things such as calling toString or testing equality you don't even have to call apply. Thus you can simply do:

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

这篇关于带有懒惰的“按名称"的参数列表("*")参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 08:10
查看更多