在很多(实际上是我用过的所有)函数式语言中,语句和表达式之间没有区别,每个代码块的最后一个值是该代码块的"返回值"。另一方面,通常不被认为是纯函数式的语言通常会引入这种区别。
作为我正在谈论的一个例子,下面的python代码打印None
:
def foo():
5 + 5
print(foo())
,而方案代码打印10
(define (foo) (+ 5 5))
(display (foo))
显然,我对那些更喜欢一种风格的人的主观答案不感兴趣,而是对客观原因感兴趣。
对我来说,这种区别似乎使语言的语法和实现变得更加复杂(一个不太明显的例子是c++标准中模板和void类型的必要例外,或者"快捷if语句"的引入,如c影响语言中的?
),而没有真正的好处-但很可能有一个原因,即使是新的,现代语言仍然有这种区别。
无处不在的副作用。
如果你使用的是纯函数式语言,那么一切都是表达式。甚至返回类似()
的"语句"(可能由它们的类型区分,例如IO ()
)。
然而,大多数编程语言默认允许在任何地方或任何地方产生效果,因此排序成为关键,因此您为计算机输入用于排序语句的特殊语法,通常用分号分隔。
对于纯表达式则不是这样,纯表达式可以按照保留表达式语义的任何顺序求值。
副作用操作被认为是特殊的表达式,因此它们具有特殊的语法。
首先,我想说,我认为你在问两个,也许更多,不同的问题:"为什么有些表达式在语法上不同于其他表达式?"one_answers"为什么排序的语义是什么?"
对于你的第一个问题:我从我读过的许多东西中得到的感觉是,语句是表达式,但是不能在所有情况下都作为子表达式出现的受限类表达式,例如,
x = 4
y = (x += 1)
上面的python代码会产生一个语法错误,因为一个语句出现在一个(不受限制的)表达式的地方。我将语句与副作用、顺序和命令式风格联系起来。我不知道你是否认为编程风格是对你问题的主观回答(风格本身当然是主观的)。
我也很想听听别人对这个问题的看法。
对于第二个问题:语义有时是任意决定的,但目标是合理的语义,不同的语言设计者只是在最合理(或最期望)的语义上有所不同。让我惊讶的是,如果在Python中控制到达函数体的末尾,它返回None,但这些都是语义。设计师必须回答类似的语义问题,如"while循环的类型应该是什么?"one_answers"如果没有else分支,if语句的类型应该是什么?"语法上应该允许这样的语句在哪里(如果这样的if语句是语句序列中的最后一个语句,可能会出现问题)?"
问题是,"为什么新的语言仍然只有语句而不是表达式?"
程序设计语言解决不同的问题,例如
- 简单语法,
- 简单实现, <
- 简单语义/gh>
是比较理论化的设计目标之一
- 结果编译代码的执行速度
- 执行程序的资源消耗
- 易于使用(例如易于阅读)
是比较实用的……
这些设计目标没有明确的定义,例如,简短的语法不一定具有最干净的结构,那么哪个更简单?
(考虑你的例子)
为了便于使用或代码的可读性,语言设计者可能会要求你在函数产生的值(或者表达式)前面写'return'。这是一个返回语句。如果你可以省略'return',它仍然是隐含的,它仍然可以被认为是一个返回语句(它只是在代码中不那么明显)。如果它被视为一个表达式,这意味着替换语义,如Scheme,但可能不是Python。从语法的角度来看,区分语句和表达式是有意义的,其中需要'return'。
看机器代码(我没有做太多,所以我可能是错的),在我看来只有语句,没有表达式。
。你的例子:
ld r1, 5
ld r2, 5
add r3, r1, r2
ret r3
(这显然是我编的)
因此,对于那些喜欢思考(冯·诺伊曼)CPU核心如何实际操作的人,或者想要简化这种目标体系结构的编译的人来说,语句是一种方式。
还有一个特殊的"邪恶"(如非函数)赋值语句。它用于表示没有递归的终止循环。根据Dijkstra的说法,循环具有比递归更简单的语义(参见E.W. Dijkstra,"编程的一门学科"1976)。与递归相比,循环执行速度更快,占用的存储空间更少。除非你的语言对尾部递归进行了优化(如Scheme)。