Pourquoi n'est-il x < y < z
pas couramment disponible dans les langages de programmation?
Dans cette réponse, je conclus que
- bien que cette construction soit triviale à implémenter dans la grammaire d'une langue et crée de la valeur pour les utilisateurs de la langue,
- les principales raisons pour lesquelles cela n'existe pas dans la plupart des langues sont dues à son importance par rapport à d'autres caractéristiques et à la réticence des organes directeurs des langues à
- déranger les utilisateurs avec des changements potentiellement décisifs
- pour mettre en œuvre la fonctionnalité (par exemple: la paresse).
introduction
Je peux parler du point de vue d'un pythoniste sur cette question. Je suis un utilisateur d'une langue avec cette fonctionnalité et j'aime bien étudier les détails de la mise en œuvre de la langue. Au-delà de cela, je connais un peu le processus de changement de langages tels que C et C ++ (la norme ISO est régie par un comité et mis à jour par année.) Et j'ai vu à la fois Ruby et Python mettre en œuvre des modifications radicales.
Documentation et implémentation de Python
Dans la documentation / grammaire, nous voyons que nous pouvons chaîner un nombre quelconque d'expressions avec des opérateurs de comparaison:
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
et la documentation indique en outre:
Les comparaisons peuvent être chaînées de façon arbitraire, par exemple, x <y <= z est équivalent à x <y et y <= z, sauf que y est évalué une seule fois (mais dans les deux cas, z n'est pas du tout évalué lorsque x <y est trouvé être faux).
Equivalence Logique
Alors
result = (x < y <= z)
est logiquement équivalent en termes d’évaluation de x
, y
et z
, à l’exception d’une y
évaluation deux fois:
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
Là encore, la différence est que y n’est évalué qu’une fois avec (x < y <= z)
.
(Notez que les parenthèses sont complètement inutiles et redondantes, mais je les ai utilisées au profit de celles venant d'autres langues, et le code ci-dessus est assez légal en Python.)
Inspection de l'arbre de syntaxe abstraite analysé
Nous pouvons vérifier comment Python analyse les opérateurs de comparaison chaînés:
>>> 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')]))])"
Nous pouvons donc voir que ce n'est vraiment pas difficile à analyser pour Python ou tout autre langage.
>>> 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')]))])"
Et contrairement à la réponse actuellement acceptée, l’opération ternaire est une opération de comparaison générique, qui prend la première expression, une itérable de comparaisons spécifiques et une itérable de noeuds d’expression à évaluer si nécessaire. Simple.
Conclusion sur Python
Personnellement, je trouve la sémantique de la gamme assez élégante et la plupart des professionnels de Python que je connais encourageraient plutôt l’utilisation de cette fonctionnalité, au lieu de la considérer comme préjudiciable - la sémantique est clairement énoncée dans la documentation réputée (comme indiqué ci-dessus).
Notez que le code est lu beaucoup plus qu'il n'est écrit. Les modifications qui améliorent la lisibilité du code doivent être acceptées et non ignorées en soulevant des spectres génériques de peur, d’incertitude et de doute .
Alors, pourquoi x <y <z n'est-il pas couramment disponible dans les langages de programmation?
Je pense qu'il y a une convergence de raisons qui sont centrées sur l'importance relative de la fonctionnalité et la relative impulsion / inertie de changement permise par les gouverneurs des langues.
Des questions similaires peuvent être posées sur d'autres fonctionnalités linguistiques plus importantes
Pourquoi l'héritage multiple n'est-il pas disponible en Java ou en C #? Il n'y a pas de bonne réponse ici à l'une ou l'autre question . Les développeurs étaient peut-être trop paresseux, comme le prétend Bob Martin, et les raisons données ne sont que des excuses. Et l'héritage multiple est un sujet assez important en informatique. C'est certainement plus important que le chaînage des opérateurs.
Des solutions simples existent
Le chaînage des opérateurs de comparaison est élégant, mais nullement aussi important que l'héritage multiple. Et tout comme Java et C # ont des interfaces comme solution de contournement, il en va de même pour chaque langage permettant des comparaisons multiples - vous chaînez simplement les comparaisons avec des booléens "et" s, ce qui fonctionne assez facilement.
La plupart des langues sont gouvernées par un comité
La plupart des langues évoluent par comité (plutôt que d’avoir un dictateur bienveillant pour la vie, comme celui de Python). Et je suppose que cette question n’a tout simplement pas été suffisamment appuyée pour pouvoir en sortir de ses comités respectifs.
Les langues qui n'offrent pas cette fonctionnalité peuvent-elles changer?
Si une langue le permet x < y < z
sans la sémantique mathématique attendue, cela constituerait un changement radical. Si cela ne le permettait pas en premier lieu, il serait presque trivial d'ajouter.
Briser les changements
En ce qui concerne les langues avec les changements les plus récents: nous mettons à jour les langages avec les changements de comportement, mais les utilisateurs ont tendance à ne pas aimer cela, en particulier les utilisateurs de fonctionnalités qui peuvent être cassées. Si un utilisateur se fie au comportement précédent de x < y < z
, il protestera probablement fort. Et comme la plupart des langues sont gouvernées par un comité, je doute que nous aurions beaucoup de volonté politique pour soutenir un tel changement.