Почему 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 вычисляется только один раз (но в обоих случаях z вообще не оценивается, когда найдено x <y) быть ложным).
Логическая эквивалентность
Так
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
Опять же, разница в том, что у оценивается только один раз (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 #? Здесь нет хорошего ответа на любой вопрос . Возможно, разработчики были слишком ленивы, как утверждает Боб Мартин, и приведенные причины являются лишь оправданиями. И множественное наследование - довольно большая тема в информатике. Это, безусловно, важнее, чем цепочка операторов.
Существуют простые обходные пути
Цепочка операторов сравнения элегантна, но отнюдь не так важна, как множественное наследование. И так же, как Java и C # имеют обходные пути интерфейсов, так и каждый язык для множественных сравнений - вы просто объединяете сравнения с логическими "и", что работает достаточно легко.
Большинство языков регулируются комитетом
Большинство языков развиваются комитетом (вместо того, чтобы иметь разумного Доброжелательного Диктатора Для Жизни, как у Питона). И я полагаю, что этот вопрос просто не получил достаточной поддержки, чтобы выйти из его соответствующих комитетов.
Могут ли языки, которые не предлагают эту функцию, измениться?
Если язык позволяет x < y < z
без ожидаемой математической семантики, это было бы серьезным изменением. Если бы он не позволял это во-первых, добавить это было бы почти тривиально.
Ломать изменения
Что касается языков с критическими изменениями: мы обновляем языки с критическими изменениями в поведении, но пользователям, как правило, это не нравится, особенно пользователям функций, которые могут быть повреждены. Если пользователь полагается на прежнее поведение x < y < z
, они, вероятно, будут громко протестовать. И поскольку большинство языков управляется комитетом, я сомневаюсь, что у нас будет много политической воли, чтобы поддержать такие изменения.