By-name repeated parameters

限于喜欢 提交于 2019-11-28 12:05:39

This isn't very pretty but it allows you to pass byname parameters 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"))

This produces

In foo

In foo f1 f2

Repeated by-name parameters are not currently supported.

If struggling for nice syntax the goal can be achieved using 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)
}

That prints:

foo: not yet evaluated.

0 1 2

3 4 5

boo: already evaluated

You can write () => String instead of Unit (it's the same thing anyway)

Thanks Randall Schulz on the good one-line answer.

I was looking for this possibility in order to make an INVARIANT tool that would run multiple asserts together. The solution I then came up with is to simply have 1..5 apply methods, since the number of varargs needed here is finite.

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
}

I posted this to show what I believe is a valid use case for varargs on 'by-name' variables. If there is a better name, please leave a comment. Thanks.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!