Чому 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
Знову ж таки, різниця полягає в тому, що 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 # мають інтерфейси як вирішення, так і кожна мова для декількох порівнянь - ви просто ланцюжок порівнянь з булевими "та" s, що працює досить легко.
Більшість мов регулюються комітетом
Більшість мов розвивається комітетом (замість того, щоб мати розумного доброзичливого диктатора на все життя, як у Python). І я припускаю, що це питання не бачило достатньої підтримки для того, щоб вийти з відповідних комітетів.
Чи можуть змінити мови, які не пропонують цю функцію?
Якщо мова дозволяє x < y < z
без очікуваної математичної семантики, це було б суттєвою зміною. Якби це не дозволило в першу чергу, було б майже тривіально додати.
Порушення змін
Щодо мов із порушеннями змін: ми оновлюємо мови з порушеннями поведінки, але користувачам це не подобається, особливо користувачам функцій, які можуть бути порушені. Якщо користувач покладається на колишню поведінку x < y < z
, він, швидше за все, голосно протестує. І оскільки більшість мов керуються комітетом, я сумніваюся, що ми отримаємо багато політичної волі для підтримки такої зміни.