4

在许多(实际上我曾经使用过的)函数式语言中,语句和表达式之间没有区别,每个代码块的最后一个值是块的“返回值”。另一方面,通常不被认为是纯粹功能性的语言通常会引入这种区别。

作为我所说的一个例子,下面的 python 代码打印None

def foo():
    5 + 5
print(foo())

而方案代码打印10

(define (foo) (+ 5 5))
(display (foo))

显然,我对喜欢一种风格而不是另一种风格的人的主观答案不感兴趣,而是客观原因。

对我来说,这种区别似乎使语言的语法和实现更加复杂(一个不太明显的例子是 c++ 标准中针对模板和 void 类型的必要例外,或者引入了“shortcut if statements”,就像?在 c - 影响的语言)没有真正的好处 - 但很可能有一个原因,即使是新的现代语言仍然具有这种区别。

4

3 回答 3

5

无处不在的副作用。

如果您使用的是纯函数式语言,那么一切都是表达式。甚至返回类似的“语句” ()(可能通过它们的类型来区分,例如IO ().

然而,大多数编程语言默认允许在任何地方或任何地方产生效果,因此排序成为关键,因此您需要使用特殊的语法来为计算机排序语句,通常用分号分隔。

这不是纯表达式的情况,它可以以保留表达式语义的任何顺序进行评估。

副作用动作被认为是特殊的表达式,它们具有特殊的语法。

于 2012-12-31T12:43:39.420 回答
4

首先,让我说我认为你在问两个,也许更多,不同的问题:“为什么有些表达在句法上与其他表达不同?” 和“为什么要对它们进行排序的语义是什么?”

对于你的第一个问题:我从我读过的很多东西中得到的感觉是,语句表达式,但是在所有情况下都不能作为子表达式出现的一类受限的表达式,例如,

x = 4
y = (x += 1)

上面的 python 代码将产生语法错误,因为语句出现在预期(不受限制的)表达式的地方。我将语句与副作用、排序和命令式风格联系起来。我不知道您是否认为编程风格是对您问题的主观回答(风格本身当然是主观的)。

我也很想听听其他人对这个问题的看法。

对于第二个问题:语义有时是任意决定的,但目标是合理的语义,不同的语言设计者只是在最合理(或最预期)上有所不同。令我惊讶的是,如果控制在 Python 中到达函数体的末尾,它会返回 None,但这些是语义。设计人员必须回答类似的语义问题,例如“while 循环的类型应该是什么?” 和“如果 if 语句没有 else 分支,它的类型应该是什么?在语法上应该在哪里允许这样的语句(如果这样的 if 语句是语句序列中的最后一个语句,可能会出现问题)?”

于 2012-12-31T06:40:54.830 回答
0

问题是,“为什么新语言仍然有语句而不是表达式?”,对吗?

编程语言设计解决不同的问题,例如

  1. 简单的语法,
  2. 简单的实现,
  3. 简单语义

属于更具理论性的设计目标和

  1. 生成的编译代码的执行速度
  2. 编译速度
  3. 执行程序的资源消耗
  4. 易于使用(例如易于阅读)

属于更实用的...

这些设计目标没有明确的定义,例如简短的语法不一定是结构最清晰的,那么哪个更简单?

(考虑到你的例子)

为了易于使用或代码可读性,语言设计者可能会要求您在函数产生的值(或者更确切地说是表达式)前面写“return”。这是一个回报声明。如果你可以省略“return”,它仍然是隐含的,它仍然可以被视为一个 return 语句(它在代码中不会那么明显)。如果将其视为表达式,则这意味着替换语义,例如 Scheme,但可能不是 Python。从句法的角度来看,区分需要“return”的语句和表达式是有意义的。

查看机器代码(我没有做太多,所以我可能错了)在我看来只有语句,没有表达式。

例如你的例子:

ld r1, 5
ld r2, 5
add r3, r1, r2
ret r3

(显然,我正在编造这个)

So for people that like to think in terms of how a (von Neumann) CPU core actually operates, or who want to simplify compilation for such a target architecture, statements are the way.

There is also the particular 'evil' (as in non-functional) assignment statement. It is required for expressing terminating loops without recursion. According to Dijkstra, loops have simpler semantics than recursion (ref. E.W. Dijkstra, "A Discipline of Programming" 1976). A loop executes faster and consumes less storage than recursion. Unless your language optimizes for tail recursion (like Scheme).

于 2013-01-01T21:06:15.937 回答