Dlaczego x < y < z
nie jest powszechnie dostępny w językach programowania?
W tej odpowiedzi stwierdzam, że
- chociaż ten konstrukt jest trywialny do wdrożenia w gramatyce języka i stanowi wartość dla użytkowników języka,
- główne powody, dla których nie występuje w większości języków, wynikają z jego znaczenia w stosunku do innych cech oraz niechęci organów zarządzających językami do
- zdenerwować użytkowników potencjalnie niszczącymi zmianami
- przejść do wdrożenia funkcji (tj. lenistwo).
Wprowadzenie
Potrafię mówić na ten temat z perspektywy Pythona. Jestem użytkownikiem języka z tą funkcją i lubię studiować szczegóły implementacji tego języka. Poza tym jestem nieco zaznajomiony z procesem zmiany języków, takich jak C i C ++ (norma ISO jest regulowana przez komitet i wersjonowana z roku na rok). Widziałem, jak zarówno Ruby, jak i Python wdrażają przełomowe zmiany.
Dokumentacja i implementacja Pythona
Z dokumentacji / gramatyki wynika, że możemy połączyć dowolną liczbę wyrażeń za pomocą operatorów porównania:
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
a dokumentacja zawiera ponadto:
Porównania można łączyć dowolnie, np. X <y <= z jest równoważne x <y i y <= z, z tym wyjątkiem, że y jest oceniane tylko raz (ale w obu przypadkach z nie jest w ogóle oceniane, gdy x <y zostanie znalezione być fałszywym).
Równoważność logiczna
Więc
result = (x < y <= z)
logicznie równoważne pod względem oceny x
, y
oraz z
z tym wyjątkiem, że y
jest wyznaczana podwójnie:
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
Znowu różnica polega na tym, że y jest oceniane tylko raz (x < y <= z)
.
(Uwaga: nawiasy są całkowicie niepotrzebne i zbędne, ale użyłem ich dla korzyści pochodzących z innych języków, a powyższy kod jest całkiem legalnym Pythonem).
Sprawdzanie przeanalizowanego abstrakcyjnego drzewa składni
Możemy sprawdzić, w jaki sposób Python analizuje łańcuchowe operatory porównania:
>>> 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')]))])"
Widzimy więc, że tak naprawdę nie jest to trudne do przeanalizowania przez Python ani żaden inny język.
>>> 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')]))])"
I w przeciwieństwie do obecnie przyjętej odpowiedzi, operacja trójskładnikowa jest ogólną operacją porównania, która wymaga pierwszego wyrażenia, iteracji określonych porównań i iteracji węzłów wyrażeń w celu oceny w razie potrzeby. Prosty.
Wnioski dotyczące Pythona
Osobiście uważam, że semantyka zakresu jest dość elegancka, a większość specjalistów Pythona, których znam, zachęciłaby do korzystania z tej funkcji, zamiast uważać ją za szkodliwą - semantyka jest dość wyraźnie określona w dobrze znanej dokumentacji (jak wspomniano powyżej).
Zauważ, że kod jest odczytywany znacznie więcej niż jest napisany. Zmiany, które poprawiają czytelność kodu, powinny zostać uwzględnione, a nie zdyskontowane poprzez podniesienie ogólnych spektrów lęku, niepewności i wątpliwości .
Dlaczego więc x <y <z nie jest powszechnie dostępny w językach programowania?
Myślę, że istnieje zbieżność przyczyn, które koncentrują się wokół względnej ważności cechy i względnego pędu / bezwładności zmiany dozwolonej przez gubernatorów języków.
Podobne pytania można zadać na temat innych ważniejszych funkcji językowych
Dlaczego wielokrotne dziedziczenie nie jest dostępne w Javie lub C #? Nie ma dobrej odpowiedzi, żeby którekolwiek z tych pytań . Być może deweloperzy byli zbyt leniwi, jak twierdzi Bob Martin, a podane powody są jedynie wymówką. Wielokrotne dziedziczenie jest dość dużym tematem w informatyce. Jest to z pewnością ważniejsze niż tworzenie łańcuchów przez operatora.
Istnieją proste obejścia
Łańcuch operatorów porównania jest elegancki, ale w żadnym wypadku nie jest tak ważny jak wielokrotne dziedziczenie. I podobnie jak Java i C # mają interfejsy jako obejście, tak też każdy język dla wielu porównań - po prostu łączysz porównania z logicznymi „i”, które działają wystarczająco łatwo.
Większość języków jest regulowana przez komitet
Większość języków ewoluuje według komisji (zamiast mieć rozsądnego Dobrotliwego Dyktatora Życia, tak jak Python). I spekuluję, że ta kwestia po prostu nie spotkała się z wystarczającym poparciem, aby wyjść z odpowiednich komisji.
Czy języki, które nie oferują tej funkcji, mogą się zmienić?
Jeśli język na to pozwala x < y < z
bez oczekiwanej semantyki matematycznej, byłaby to przełomowa zmiana. Gdyby przede wszystkim na to nie pozwalał, dodanie tego byłoby prawie trywialne.
Przełamywanie zmian
Jeśli chodzi o języki z przełomowymi zmianami: aktualizujemy języki z przełomowymi zmianami zachowania - ale użytkownikom się to nie podoba, szczególnie użytkownikom funkcji, które mogą być zepsute. Jeśli użytkownik polega na poprzednim zachowaniu x < y < z
, prawdopodobnie głośno zaprotestowałby. A ponieważ większość języków jest zarządzana przez komisję, wątpię, byśmy mieli dużo woli politycznej, aby poprzeć taką zmianę.