Depuis le guide du langage Java 5 :
Lorsque vous voyez les deux points (:), lisez-le comme "in".
Pourquoi ne pas utiliser in
en premier lieu alors?
Cela me dérange depuis des années. Parce que c'est incompatible avec le reste de la langue. Par exemple, en Java il y a implements
, extends
, super
pour les relations entre les types de symboles au lieu comme en C ++, Scala ou Ruby.
En Java deux points utilisé dans 5 contextes . Trois d'entre eux sont hérités de C. Et deux autres ont été approuvés par Joshua Bloch. Du moins, a-t-il dit lors de la conférence "La controverse sur les fermetures" . Cela se produit lorsqu'il critique l'utilisation d'un deux-points pour le mappage comme incompatible avec la sémantique de for-each. Ce qui me semble étrange parce que ce sont les modèles attendus pour chaque abus. Comme list_name/category: elements
ou laberl/term: meaning
.
J'ai fouillé jcp et jsr, mais je n'ai trouvé aucun signe de liste de diffusion. Google n'a trouvé aucune discussion à ce sujet. Seuls les débutants confondus par la signification de deux points en for
.
Principaux arguments contre in
fournis jusqu'à présent:
- nécessite un nouveau mot-clé; et
- complique le lexisme.
Regardons les définitions de grammaire pertinentes :
déclaration : instruction 'for' '(' forControl ')' | ... ; forControl : EnhancedForControl | forInit? ";" expression? ";" forUpdate? ; EnhancedForControl : variableModifier * type variableDeclaratorId ':' expression ;
Changez de :
pour in
ne pas apporter de complexité supplémentaire ou nécessite un nouveau mot clé.
Réponses:
Les analyseurs normaux tels qu'ils sont généralement enseignés ont une étape de lexer avant que l'analyseur touche l'entrée. Le lexer (également «scanner» ou «tokenizer») coupe l'entrée en petits jetons annotés avec un type. Cela permet à l'analyseur principal d'utiliser des jetons comme éléments terminaux plutôt que d'avoir à traiter chaque personnage comme un terminal, ce qui entraîne des gains d'efficacité notables. En particulier, le lexer peut également supprimer tous les commentaires et espaces blancs. Cependant, une phase de tokenizer distincte signifie que les mots-clés ne peuvent pas également être utilisés comme identifiants (à moins que le langage ne prenne en charge le stropping qui est quelque peu tombé en disgrâce, ou préfixe tous les identifiants avec un sigil
$foo
).Pourquoi? Supposons que nous ayons un simple jeton qui comprend les jetons suivants:
Le tokenizer correspondra toujours au jeton le plus long et préférera les mots clés aux identifiants. Alors
interesting
sera lexed commeIDENT:interesting
, maisin
sera lexed queIN
, jamaisIDENT:interesting
. Un extrait de code commesera traduit dans le flux de jetons
Jusqu'à présent, cela fonctionne. Mais toute variable
in
serait lexée comme mot cléIN
plutôt que comme variable, ce qui casserait le code. Le lexer ne conserve aucun état entre les jetons, et ne peut pas savoir que celain
devrait généralement être une variable sauf lorsque nous sommes dans une boucle for. De plus, le code suivant doit être légal:Le premier
in
serait un identifiant, le second serait un mot-clé.Il y a deux réactions à ce problème:
Les mots clés contextuels prêtent à confusion, réutilisons plutôt les mots clés.
Java a de nombreux mots réservés, dont certains n'ont aucune utilité, sauf pour fournir des messages d'erreur plus utiles aux programmeurs passant à Java à partir de C ++. L'ajout de nouveaux mots clés rompt le code. L'ajout de mots clés contextuels est source de confusion pour le lecteur du code, à moins qu'ils ne présentent une bonne mise en évidence de la syntaxe, et rend l'outillage difficile à implémenter car ils devront utiliser des techniques d'analyse plus avancées (voir ci-dessous).
Lorsque nous voulons étendre la langue, la seule approche sensée consiste à utiliser des symboles qui n'étaient pas légaux auparavant dans la langue. En particulier, il ne peut s'agir d'identifiants. Avec la syntaxe de boucle foreach, Java a réutilisé le
:
mot-clé existant avec une nouvelle signification. Avec lambdas, Java a ajouté un->
mot - clé qui ne pouvait pas apparaître auparavant dans un programme légal (-->
serait toujours lexé comme'--' '>'
étant légal, et->
aurait pu être lexé auparavant'-', '>'
, mais cette séquence serait rejetée par l'analyseur).Les mots clés contextuels simplifient les langues, implémentons-les
Les Lexers sont incontestablement utiles. Mais au lieu d'exécuter un lexer avant l'analyseur, nous pouvons les exécuter en tandem avec l'analyseur. Les analyseurs ascendants connaissent toujours l'ensemble des types de jetons qui seraient acceptables à n'importe quel emplacement donné. L'analyseur peut alors demander au lexer de faire correspondre l'un de ces types à la position actuelle. Dans une boucle for-each, l'analyseur serait à la position indiquée
·
dans la grammaire (simplifiée) une fois la variable trouvée:À cette position, les jetons légaux sont
SEMICOLON
ouIN
, mais pasIDENT
. Un motin
- clé serait totalement sans ambiguïté.Dans cet exemple particulier, les analyseurs descendants n'auraient pas de problème non plus puisque nous pouvons réécrire la grammaire ci-dessus pour
et tous les jetons nécessaires à la décision peuvent être vus sans retour en arrière.
Tenez compte de la convivialité
Java a toujours tendu vers la simplicité sémantique et syntaxique. Par exemple, le langage ne prend pas en charge la surcharge des opérateurs car cela rendrait le code beaucoup plus compliqué. Ainsi, lorsque nous décidons entre
in
et:
pour une syntaxe de boucle pour chaque, nous devons considérer laquelle est moins déroutante et plus apparente pour les utilisateurs. Le cas extrême serait probablement(Remarque: Java a des espaces de noms distincts pour les noms de type, les variables et les méthodes. Je pense que c'était surtout une erreur. Cela ne signifie pas que la conception de langage ultérieure doit ajouter plus d' erreurs.)
Quelle alternative offre des séparations visuelles plus claires entre la variable d'itération et la collection itérée? Quelle alternative peut être reconnue plus rapidement lorsque vous regardez le code? J'ai trouvé que séparer les symboles valait mieux qu'une chaîne de mots en ce qui concerne ces critères. D'autres langues ont des valeurs différentes. Par exemple, Python énonce de nombreux opérateurs en anglais afin qu'ils puissent être lus naturellement et sont faciles à comprendre, mais ces mêmes propriétés peuvent rendre assez difficile la compréhension d'un morceau de Python en un coup d'œil.
la source
La syntaxe de boucle for-each a été ajoutée en Java 5. Vous devez créer
in
un mot-clé de langue, et ajouter des mots-clés à une langue plus tard est quelque chose que vous évitez à tout prix car cela casse le code existant - soudain, toutes les variables nomméesin
provoquent une analyse Erreur.enum
était déjà assez mauvais à cet égard.la source
in
aurait signifié introduire un nouveau mot-clé, brisant ainsi la compatibilité descendante (System.in
, n'importe qui?) Ou introduire un tout nouveau concept inconnu auparavant (mots-clés contextuels). Tout pour quel gain?for(variable in expression)
ne peut jamais être ambigu avec un code juridique, même si «in» peut être utilisé pour des variables. Cependant, une phase de lexer distincte est assez courante dans de nombreuses chaînes d'outils du compilateur. Cela rendrait impossible ou du moins beaucoup plus difficile d'analyser Java avec certains générateurs d'analyseurs courants. Garder la syntaxe d'un langage simple est généralement bon pour toutes les personnes impliquées; tout le monde n'a pas besoin de monstruosités syntaxiques comme C ++ ou Perl.const
et cegoto
sont des mots réservés en Java, mais ils ne sont pas (encore) utilisés.