按名称重复参数

Posted

技术标签:

【中文标题】按名称重复参数【英文标题】:By-name repeated parameters 【发布时间】:2011-02-12 00:37:36 【问题描述】:

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

以下代码无法运行:

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

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

【问题讨论】:

重复:***.com/questions/2618891/… 在这种情况下您要使用按名称参数的原因是什么?也许我们可以提出更好的解决方案。 【参考方案1】:

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

【讨论】:

【参考方案2】:

这不是很漂亮,但它允许您通过 varargs 样式传递 byname 参数

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 中

在富 f1 f2

【讨论】:

看和写肯定不愉快。我继续鼓励人们区分名称参数(使用 thunk 实现,但在逻辑上不同)和用作参数的函数值。方法和函数也是如此。 我认为 Randall 的 cmets 是公平的,以上内容可以通过辅助函数来包装/预处理参数进行改进,例如: def deferred(block: => String) = () = > 带有 foo 的块更改为: def foo(s: (() => String)*) 给予,例如: foo(deferred val a = "apples"; "Green "+apples, deferred "Pears" )【参考方案3】:

如果为漂亮的语法而苦苦挣扎,则可以使用隐式来实现目标。

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

嘘:已经评估过

【讨论】:

【参考方案4】:

它适用于 Scala 3:

scala> def f(i: => Int*): Int = i.sum
def f(i: => Int*): Int

scala> f(1, 2, 3)
val res0: Int = 6

【讨论】:

【参考方案5】:

你可以写() =&gt; String而不是Unit(反正都是一样的)

【讨论】:

这真的不是“一回事”。在方法中调用和使用它们的语义和语法都不同。【参考方案6】:

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

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

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

我发布此内容是为了展示我认为在“按名称”变量上使用 varargs 的有效用例。如果有更好的名字,欢迎留言。谢谢。

【讨论】:

以上是关于按名称重复参数的主要内容,如果未能解决你的问题,请参考以下文章

根据参数名称为函数分配参数[重复]

按名称传递参数

获取变量或参数的名称[重复]

Python 装饰器按名称访问参数

Npgsql 按名称将参数传递给存储的函数

成员名称和构造函数参数名称之间的冲突[重复]