Scala方法参数-结合变量参数和默认参数



是否可以在Scala方法函数定义中组合变量参数和默认参数?具体来说,我正在尝试编写一个具有以下签名的补丁方法:

def patch(body: String, contentType: ContentType = ContentType.APPLICATION_JSON, customHeaders: (String, String)*)

我得到错误Parameter section with *-parameter cannot have default arguments。所以我认为这是一个参数排序的问题。但是,我需要将*-参数放在最后。

我的问题是:

  • 为什么*-参数必须是最后一个?编译器是否可以轻松地解析参数?

  • 为什么*-parameter不能在默认参数之后?我认为相同的参数适用于编译器更容易解析参数的地方,因为默认参数和变量参数都是可选的。

为什么*-参数必须是最后一个?

从技术上讲,即使*-参数没有被限制为最后一个,编译器也应该能够计算出来。这个SO链接提供了一些关于可能原理的见解(尽管是非官方的(。

为什么*-parameter不能在默认参数之后?

如果允许在默认参数之后使用*-parameter,则在某些情况下,应为哪些参数变量分配所提供的参数会有歧义。例如:

def foo(a: String = "hi", bs: String*) = a + " " + bs.mkString(" ")
foo("hello", "world")  // Should "hello" go to `a` or be a part of `bs`?

请注意,从技术上讲,这种限制也可以取消,例如,在出现歧义的情况下(例如foo(a="hello", "world")(,需要显式参数变量分配。

为了规避限制,你可以使用currying(这允许你在每个参数列表中有一个*-参数(:

def bar(s: String, i: Int = 1, ts: (String, String)*) =
ts.map(t => (t._1 + s*i, t._1 + s*i))
// <console>:23: error: a parameter section with a `*'-parameter is not allowed to have default arguments
//        def bar(s: String, i: Int = 1, ts: (String, String)*) = {
def bar(s: String, i: Int = 1)(ts: (String, String)*) =
ts.map(t => (t._1 + s*i, t._2 + s*i))
bar("!", 2)(("a", "b"), ("c", "d"))
// res1: Seq[(String, String)] = ArrayBuffer((a!!,b!!), (c!!,d!!))

最新更新