【问题标题】:Scala Method Parameters - Combining variable arguments and default parametersScala 方法参数 - 结合可变参数和默认参数
【发布时间】:2018-10-26 22:59:56
【问题描述】:

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

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

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

我的问题是:

  • 为什么*-参数必须放在最后?是不是这样编译器就可以轻松解析参数了?

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

【问题讨论】:

    标签: scala methods


    【解决方案1】:

    为什么*-参数必须放在最后?

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

    为什么 *-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"))。

    为了规避限制,您可以使用柯里化(它允许您为每个参数列表提供一个 * 参数):

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

    【讨论】:

    • “如果允许在默认参数之后使用 *-parameter,则在某些情况下应该为参数变量分配所提供的参数会产生歧义。” - 并不真地。想出易于理解的规则来消除歧义非常简单。这只是一种设计选择。
    • @Jörg W Mittag,我认为你是对的。除其他原因外,设计选择可能基于“*-参数必须是最后一个”的决定,以及默认参数放在最后更实际有用的事实。我在答案中添加了相关注释。
    猜你喜欢
    • 1970-01-01
    • 2011-05-07
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    相关资源
    最近更新 更多