【问题标题】:Why does leaving the dot out in foldLeft cause a compilation error?为什么将点放在 foldLeft 中会导致编译错误?
【发布时间】:2012-10-05 23:29:56
【问题描述】:

谁能解释为什么我在应用foldLeft 函数时省略点符号时会看到以下编译错误?(2.9.2 版)

scala> val l = List(1, 2, 3)
res19: List[Int] = List(1 ,2 ,3)

scala> l foldLeft(1)(_ * _)
<console>:9: error: Int(1) does not take parameters
                    l foldLeft(1)(_ * _)
                                    ^

但是

scala> l.foldLeft(1)(_ * _) 
res27: Int = 6

这不适用于其他高阶函数,例如 map,它似乎并不关心我是否提供点。

我不认为这是关联性的事情,因为我不能只调用 foldLeft(1)

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    这是因为 foldLeft 是咖喱。除了使用点符号外,您还可以通过添加括号来解决此问题:

    scala> (l foldLeft 1)(_ * _)
    res3: Int = 6
    

    哦 - 关于您关于无法调用 foldLeft(l) 的评论,您可以,但您需要像这样部分应用它:

    scala> (l foldLeft 1) _
    res3: ((Int, Int) => Int) => Int = <function1>
    

    【讨论】:

    • 感谢建设性注释,我的问题的完整答案在于您对 Regis 的帖子发表的关于解析器如何攻击表达式的第一条评论。
    【解决方案2】:

    省略点是可能的,因为 scala 对中缀表示法的语法支持,它需要 3 个部分:

    leftOperand operator rightOperand. 
    

    但是因为foldLeft有两个参数列表,所以你最终在句法级别有4个部分:lfoldLeft(1)(_ * _)

    不适合中缀表示法,因此出现错误。

    【讨论】:

    • 这可能是理解中缀表示法何时有用的一个很好的经验法则,但我不确定它是否完全准确。可以使用中缀表示法调用foldLeft(如我之前的回答所示)。问题是解析器将l fold left(1)(_ * _) 解析为l foldLeft((1)(_ * _)) 而不是(l foldLeft(1))(_ * _)
    • 你的工作实际上证明了我的观点。您正在强制部分应用 foldLeft 以便拥有 3 个部分,这使得中缀表示法成为可能。结果是一个函数,您可以立即调用。
    • 对不起 - 这只是我的迂腐,但错误不是由于编译器拒绝中缀表示法。这是由于编译器试图将(_ * _) 应用于(1),但它不能。
    • (grr - 刚刚注意到我的 Mac 在我之前的评论中将foldLeft“更正”为fold left
    • 我没有说这是因为中缀符号被拒绝了。抱歉,我可能太难以捉摸,并且可能会产生误导。关键是foldLeft (1) (_ * _) 不适合中缀表示法。无论编译器可以尝试如何理解这个表达式,这肯定不是预期的(幸运的是,它只是无法编译,但在其他类似情况下,它可能会编译并做一些意想不到的事情)。
    猜你喜欢
    • 2011-06-09
    • 1970-01-01
    • 2023-03-03
    • 2019-08-30
    • 2014-05-23
    • 1970-01-01
    • 2010-09-18
    • 2018-04-08
    • 2020-04-26
    相关资源
    最近更新 更多