0

在 JavaScript 中,

f = function(x) {
    return x + 1;
}
(5)

乍一看好像应该分配f后继函数,但实际上分配了值 6,因为解析器将括号后面的 lambda 表达式解释为后缀表达式,特别是函数调用。幸运的是,这很容易解决:

f = function(x) {
    return x + 1;
};
(5)

表现如预期。

如果 Python 允许在 lambda 表达式中使用块,则会出现类似的问题:

f = lambda(x):
    return x + 1
(5)

但是这次我们不能用同样的方法解决它,因为没有分号。在实践中,Python 通过不允许多行 lambda 表达式来避免这个问题,但我正在研究一种具有基于缩进的语法的语言,我确实需要多行 lambda 和其他表达式,所以我试图弄清楚如何避免出现块解析为后缀表达式的开头。到目前为止,我在想也许递归下降解析器的每个级别都应该有一个参数,类似于“我们已经在这个语句中吃掉了一个块,所以不要做后缀”。

是否有任何现有的语言遇到此问题,如果有,他们如何解决?

4

2 回答 2

1

在 Haskell 中,假设解析器处于布局敏感模式,每当您以与前一行相同的缩进开始一行时,都会有一个隐式分号。

更具体地说,在遇到表示(布局敏感)块开始的标记后,会记住第一个块项的第一个标记的缩进级别。缩进更多的每一行继续当前块项;缩进相同的每一行都开始一个新的块项目,而缩进较少的第一行意味着该块的关闭。

如何处理您的最后一个示例取决于是否f =是某个块中的块项目。如果是,那么 lambda 表达式和 之间将有一个隐式分号(5),因为后者的缩进与前者相同。如果不是,(5)则将被视为继续作为f =其一部分的任何块项目,使其成为 lamda 函数的参数。

细节比这有点混乱;查看Haskell 2010 报告

于 2013-09-17T11:46:18.700 回答
1

Python分号。这是完全有效的(虽然丑陋且不推荐)Python 代码:f = lambda(x): x + 1; (5).

不过,在其他标准 Python 语法中,多行 lambda 表达式还有许多其他问题。它与 Python 如何处理表达式内部的缩进(实际上通常是空格)完全不兼容 - 它不兼容,这与您想要的完全相反。您应该阅读有关多行 lambda 的大量 python-ideas 线程。它介于非常困难和不可能之间。

如果您想在 lambdas 中使用任意复杂的复合语句,即使您制作了所有语句表达式,也不能将现有规则用于多行表达式。您必须更改缩进处理(请参阅语言参考了解它现在的工作方式),以便表达式也可以包含块。如果不破坏完美的 Python 代码,这是很难做到的,并且肯定会导致许多 Python 程序员在几个方面认为语言更糟:更难理解、实现更复杂、允许一些愚蠢的错误等。

大多数语言根本没有解决这个确切的问题。大多数候选者(Scala、Ruby、Lisps 和这三者的变体)都有明确的块结束标记。我知道两种具有相同问题的语言,其中一种(Haskell)已被另一个答案提到。Coffeescript 还使用没有块尾标记的缩进。它会正确解析您的示例的音译。但是,我找不到任何关于它如何或为什么这样做的规范(我不会深入研究解析器源代码)。两者在语法和设计理念上都与 Python 有很大不同,因此它们的解决方案对 Python 几乎没有用处(如果有的话)。

于 2013-09-17T14:50:09.120 回答