按名称重复参数

时间:2010-04-25 04:46:55

标签: scala functional-programming variadic-functions lazy-evaluation

如何在Scala中传递按名称重复的参数?

以下代码无效:

scala> def foo(s: (=> String)*) = {
<console>:1: error: no by-name parameter type allowed here
       def foo(s: (=> String)*) = {
                   ^

有没有其他方法可以将可变数量的名称参数传递给方法?

5 个答案:

答案 0 :(得分:10)

目前不支持重复的名称参数。

答案 1 :(得分:3)

这不是很漂亮,但它允许你传递byname参数varargs style

def printAndReturn(s: String) = {
  println(s)
  s
}

def foo(s: (Unit => String)*) {
  println("\nIn foo")
  s foreach {_()}  // Or whatever you want ...
}

foo()

foo((Unit) => printAndReturn("f1"),
    (Unit) => printAndReturn("f2"))

这会产生

在foo

在foo F1 F2

答案 2 :(得分:2)

如果努力获得良好的语法,可以使用implicits实现目标。

implicit def arg2func(arg: ⇒ Byname): (() => Byname) = () ⇒ arg

def foo(params: (() ⇒ Byname)*): Unit = {
    println("foo: not yet evaluated.")
    params.foreach(_())
}

def boo(params: Byname*): Unit = {
    println("boo: already evaluated")
}

foo(Byname(0), Byname(1), Byname(2))
println()
boo(Byname(3), Byname(4), Byname(5))

case class Byname(n: Int) {
    println(n)
}

打印:

  

foo:尚未评估。

     

0 1 2

     

3 4 5

     

boo:已经评估

答案 3 :(得分:0)

您可以写() => String而不是单位(无论如何都是相同的)

答案 4 :(得分:0)

感谢Randall Schulz提供了良好的单行答案。

我一直在寻找这种可能性,以便制作一个可以同时运行多个断言的INVARIANT工具。我接下来提出的解决方案是简单地使用1..5 apply方法,因为这里需要的varargs数量是有限的。

object INVARIANT {
  def apply = {}
  def apply( conds: => Boolean * ) = {    // DOES NOT COMPILE
    conds.foreach( assert(_) )
  }
}

object TestX extends App {

  class A {
    println("A body")
    INVARIANT( true )
  }

  class B extends A {
    println("B body")
    INVARIANT( true, false )  
  }

  new B
}

我发布了这个以显示我认为对'by-name'变量的varargs的有效用例。如果有更好的名字,请发表评论。感谢。