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

时间:2018-10-26 22:59:57

标签: scala methods

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

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

我收到错误Parameter section with *-parameter cannot have default arguments。因此,我认为这是对参数进行排序的问题。但是,我必须最后放置*参数。

我的问题是:

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

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

1 个答案:

答案 0 :(得分:3)

  

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

从技术上讲,即使*参数不限于最后一个,编译器也应该能够弄清楚。 SO link为可能的原理提供了一些见解(尽管是非正式的)。

  

为什么*参数不能在默认参数之后出现?

如果在默认参数后允许* -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")要求显式的变量变量赋值)来解除此限制。

要规避该限制,您可以求助于curring(这使您可以在每个参数列表中使用*参数):

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!!))