使用命名参数调用具有可变参数的函数的Scala语法是什么?

6

假设我有一个函数:

def f(a:Int = 0, b:String = "", c:Float=0.0, foos: Foo*) { ... }

请注意一些参数的默认参数的使用。通常,要使用默认值,您可以通过以下方式使用命名参数调用函数:

val foo = Foo("Foo!")
f(foos = foo)

这个语法是有效的,因为我只用一个foo调用了这个方法。然而,如果我有两个或更多的foo,那么这个语法就不再适用了。
val foo1 = Foo("Foo!")
val foo2 = Foo("Bar!")
f(foos = ...)

这里需要输入什么并不是很明显。 Seq(foo1,foo2)Seq(foo1,foo2):_* 都无法通过类型检查。

此外,如果我没有任何 foo,我该如何调用它?

// All out of foos!
f(foos = ...)

对于这种情况,使用空括号(f())调用函数是无效的。
谢谢!

你使用的是哪个版本的Scala?在2.9.2中,尝试在REPL中定义f会出现“<console>:9: error: a parameter section with a `*'-parameter is not allowed to have default arguments”的错误。 - Paolo Falabella
我也在2.9.2上看到了这个问题。然而,我正在编译的实际代码运行的是2.9.1,在那里显然是合法的。 - fatuhoku
2个回答

8

关于默认参数,请参考我对您问题的评论。关于如何使用命名参数调用可变参数部分,请参见下文(scala 2.9.2):

scala> case class Foo(a:Int)
defined class Foo

scala> def f(a:Int, foos: Foo*) = foos.length
f: (a: Int, foos: Foo*)Int

scala> f(a=2, foos=Foo(2))
res0: Int = 1

// I'm not sure if this is cheating...
// am I just naming the first of the two variadic arguments?
scala> f(a=2, foos=Foo(2),Foo(3))
res1: Int = 2

//anyway you can do ....
scala> f(a=2, foos=Seq(Foo(1), Foo(2)):_*)
res2: Int = 2

// with no foos...
scala> f(a=2, foos=Nil:_*)
res3: Int = 0

谢谢,这让我非常清楚。我会接受你的答案,因为它更符合问题,但实际上我认为我会采用bluenote10的方法。 - fatuhoku

7

考虑到Paolo所提到的Scala 2.9限制,您仍可以使用柯里化将参数分为不同的部分,其中一部分使用带有默认参数的命名参数,另一部分用于varargs(或如果您需要多个vararg参数则使用多个柯里化参数部分)。就可读性而言,结果几乎比仅使用命名参数更好(imho):

f(b="something")()
f(c=3.14)(foo1, foo2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接