为什么x < y < z
在编程语言中通常不可用?
在这个答案中,我得出结论:
- 尽管这种构造对于用语言的语法实现来说是微不足道的,并且可以为语言用户创造价值,
- 大多数语言中不存在该语言的主要原因是由于它相对于其他功能的重要性以及语言管理机构不愿意使用任何一种语言
- 可能会给用户带来重大变化而使用户不满
- 移动以实现该功能(即懒惰)。
介绍
我可以从Pythonist的角度谈这个问题。我是具有此功能的语言的用户,并且我想研究该语言的实现细节。除此之外,我对更改C和C ++等语言(ISO标准由委员会管理并按年份进行版本化)的过程有些熟悉,并且我已经看到Ruby和Python都实现了重大更改。
Python的文档和实现
从文档/语法中,我们看到可以使用比较运算符链接任意数量的表达式:
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
并且文档进一步指出:
比较可以任意链接,例如,x <y <= z等效于x <y和y <= z,除了y仅被评估一次(但是在两种情况下,当x <y被发现时,z都不被评估。是假的)。
逻辑对等
所以
result = (x < y <= z)
在评估,和时在逻辑上是等效的x
,但两次评估除外:y
z
y
x_lessthan_y = (x < y)
if x_lessthan_y: # z is evaluated contingent on x < y being True
y_lessthan_z = (y <= z)
result = y_lessthan_z
else:
result = x_lessthan_y
同样,区别在于y仅用评估一次(x < y <= z)
。
(请注意,括号是完全不必要和多余的,但是我使用它们是出于其他语言的好处,并且上面的代码是合法的Python。)
检查解析的抽象语法树
我们可以检查Python如何解析链式比较运算符:
>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
comparators=[Str(s='bar'), Str(s='baz')]))])"
因此,我们可以看到,对于Python或任何其他语言而言,解析它确实并不困难。
>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"
与当前接受的答案相反,三元运算是一种通用比较运算,它采用第一个表达式,特定比较的可迭代项和表达式节点的可迭代项进行必要的评估。简单。
关于Python的结论
我个人发现范围语义非常优雅,并且我认识的大多数Python专业人士都鼓励使用该功能,而不是考虑它具有破坏性-语义已在声誉卓著的文档中明确说明(如上所述)。
请注意,读取的代码远比编写的要多。应该接受能够提高代码的可读性的更改,而不应通过提高恐惧,不确定性和怀疑等通用特性来加以接受。
那么为什么x <y <z在编程语言中通常不可用?
我认为,有多种原因合在一起,围绕该功能的相对重要性以及语言的总督所允许的相对变化动量/惯性。
关于其他更重要的语言功能,可以问类似的问题
为什么Java或C#中没有多重继承?这两个问题都没有好的答案。正如鲍勃·马丁(Bob Martin)所说,也许开发人员太懒了,给出的理由仅仅是借口。多重继承是计算机科学中一个相当大的话题。当然,它比操作员链接更重要。
存在简单的解决方法
比较运算符链接很优雅,但绝不比多重继承重要。就像Java和C#具有接口作为解决方法一样,每种语言都可以进行多次比较-您只需将比较与布尔“和”链接起来即可,这很容易工作。
大多数语言受委员会管辖
大多数语言都是由委员会发展而来的(而不是像Python那样拥有明智的人生独裁者)。我推测这个问题尚未得到足够的支持,无法使其脱离其各自的委员会。
不提供此功能的语言可以更改吗?
如果一种语言允许x < y < z
没有预期的数学语义,那将是一个重大的改变。如果一开始不允许这样做,那么添加它几乎是微不足道的。
重大变化
关于具有重大更改的语言:我们确实具有重大更改来更新语言-但是用户往往不喜欢这种行为,尤其是那些可能已破坏功能的用户。如果用户依赖的先前行为x < y < z
,则他们可能会大声抗议。而且由于大多数语言都是由委员会管理的,所以我怀疑我们是否会获得支持这种改变的政治意愿。