Neden herkes için “in” yerine iki nokta üst üste vardır?


9

Java 5 dil kılavuzundan :

İki nokta üst üste işaretini (:) gördüğünüzde "in" olarak okuyun.

Neden inilk etapta kullanmıyorsunuz ?

Bu beni yıllardır rahatsız ediyor. Çünkü dilin geri kalanıyla tutarsız. Örneğin, orada Java implements, extends, superC ++, Scala veya Ruby gibi türleri yerine semboller arasındaki ilişkileri için.

Java kolonunda 5 bağlamda kullanılır . Üçü C'den miras alınır ve diğer ikisi Joshua Bloch tarafından onaylanmıştır. En azından "kapanış tartışması" konuşması sırasında böyle oldu . Bu, her semantik için tutarsız olarak eşleme için bir kolon kullanımını eleştirdiğinde ortaya çıkar. Hangisi garip görünüyor çünkü her istismar için beklenen desen. Gibi list_name/category: elementsveya laberl/term: meaning.

Ben jcp ve jsr etrafında snooped, ancak posta listesi belirtisi bulamadı. Google tarafından bu konuda hiçbir tartışma bulunamadı. Sadece yeni başlayanlar kolonun anlamı ile karıştı for.


inŞimdiye kadar sunulan karşıtı tartışmalar :

  • yeni anahtar kelime gerektirir; ve
  • lexing karmaşık.

İlgili dilbilgisi tanımlarına bakalım :

Beyan
    : 'for' '(' forControl ')' ifadesi
    | ...
    ;

forControl
    : gelişmiş forControl
    | forInit? ';' ifadesi? ';' forUpdate?
    ;

enhancedForControl
    : variableModifier * type variableDeclaratorId ':' ifade
    ;

Ek karmaşıklık getirmemek :için değiştirin inveya yeni anahtar kelime gerektirir.


1
Dil tasarımcılarının motivasyonlarını bulmak için en iyi kaynak genellikle tasarımcıların kendisidir. Bununla birlikte, görünüşe göre sadece bir tekrarlanabilir üzerinde sözdizimsel şeker; bkz. stackoverflow.com/questions/11216994/…
Robert Harvey

Yanıtlar:


8

Genel olarak öğretildikleri gibi normal ayrıştırıcılar, ayrıştırıcı girdiye dokunmadan önce bir lexer aşamasına sahiptir. Lexer (ayrıca “tarayıcı” veya “belirteç”), girdiyi bir türle ek açıklamalı küçük belirteçlere böler. Bu, ana ayrıştırıcının, her bir karakteri bir terminal olarak ele almak yerine jetonları terminal öğeleri olarak kullanmasına izin verir, bu da fark edilir verimlilik kazanımlarına yol açar. Özellikle, lexer tüm yorumları ve beyaz alanı da kaldırabilir. Bununla birlikte, ayrı bir belirteç aşaması, anahtar kelimelerin tanımlayıcı olarak da kullanılamayacağı anlamına gelir (dil , bir miktar lehinden düşmeyi desteklemiyorsa veya tüm tanımlayıcılara sigil benzeri ön ekler eklemezse$foo ).

Neden? Aşağıdaki belirteçleri anlayan basit bir belirteçimiz olduğunu varsayalım:

FOR = 'for'
LPAREN = '('
RPAREN = ')'
IN = 'in'
IDENT = /\w+/
COLON = ':'
SEMICOLON = ';'

Belirteç her zaman en uzun belirteçle eşleşir ve tanımlayıcılara göre anahtar kelimeleri tercih eder. Bu interestingşekilde olduğu gibi IDENT:interesting, ama asla olduğu gibi inlexedilecektir . Gibi bir kod snippet'iINIDENT:interesting

for(var in expression)

jeton akışına çevrilecek

FOR LPAREN IDENT:var IN IDENT:expression RPAREN

Şimdiye kadar, bu işe yarıyor. Ancak herhangi bir değişken, kodu kıracak bir değişken yerine inanahtar kelime olarak adlandırılır IN. Lexer, jetonlar arasında herhangi bir durum tutmaz ve inbir for döngüsünde olduğumuz durumlar dışında bunun genellikle bir değişken olması gerektiğini bilemez . Ayrıca, aşağıdaki kod yasal olmalıdır:

for(in in expression)

Birincisi inbir tanımlayıcı, ikincisi bir anahtar kelime olacaktır.

Bu soruna iki tepki var:

İçeriğe dayalı anahtar kelimeler kafa karıştırıcıdır, bunun yerine anahtar kelimeleri tekrar kullanalım.

Java'nın, C ++ 'dan Java'ya geçiş yapan programcılara daha yararlı hata mesajları sağlamak dışında bir faydası olmayan birçok ayrılmış kelime vardır. Yeni anahtar kelimeler eklemek kodu kırıyor. Bağlamsal anahtar kelimeler eklemek, iyi bir sözdizimi vurgulaması olmadıkça kod okuyucusunu kafa karıştırıcıdır ve daha gelişmiş ayrıştırma teknikleri kullanmaları gerekeceğinden araçların uygulanmasını zorlaştırır (aşağıya bakın).

Dili genişletmek istediğimizde, aklı başında olan tek yaklaşım daha önce dilde yasal olmayan semboller kullanmaktır. Özellikle, bunlar tanımlayıcı olamaz. Foreach döngü sözdizimiyle Java, mevcut :anahtar kelimeyi yeni bir anlamla yeniden kullandı . Lambdas ile Java, ->daha önce herhangi bir yasal programda bulunamayan bir anahtar kelime ekledi ( -->yine de yasal olduğu gibi lexedilmiş '--' '>'ve ->daha önce olduğu gibi lexedilmiş olabilir '-', '>', ancak bu sıra ayrıştırıcı tarafından reddedilir).

İçeriğe dayalı anahtar kelimeler dilleri basitleştirir, bunları uygulayalım

Lexers tartışmasız faydalıdır. Ancak ayrıştırıcıdan önce bir lexer çalıştırmak yerine bunları ayrıştırıcı ile birlikte çalıştırabiliriz. Aşağıdan yukarıya ayrıştırıcılar her zaman, herhangi bir yerde kabul edilebilir olan token türleri kümesini bilir. Ayrıştırıcı daha sonra lexer'ın bu türden herhangi biriyle geçerli konumda eşleşmesini isteyebilir. Her biri için bir döngüde, ayrıştırıcı ·, değişken bulunduktan sonra (basitleştirilmiş) dilbilgisinde belirtilen konumda olacaktır :

for_loop = for_loop_cstyle | for_each_loop
for_loop_cstyle = 'for' '(' declaration · ';' expression ';' expression ')'
for_each_loop = 'for' '(' declaration · 'in' expression ')'

Bu pozisyonda, yasal jetonlar SEMICOLONya da INdeğil IDENT. Bir anahtar kelime intamamen açık olur.

Bu özel örnekte, yukarıdan aşağıya ayrıştırıcıların da sorunu yoktur, çünkü yukarıdaki dilbilgisini yeniden yazabiliriz.

for_loop = 'for' '(' declaration · for_loop_rest ')'
for_loop_rest =  · ';' expression ';' expression
for_loop_rest = · 'in' expression

ve karar için gerekli tüm jetonlar geri izlenmeden görülebilir.

Kullanılabilirliği düşünün

Java her zaman anlamsal ve sözdizimsel sadeliğe yönelmiştir. Örneğin, dil, operatörün aşırı yüklenmesini desteklemez, çünkü kod çok daha karmaşık hale gelir. Bu nedenle, her döngü için bir sözdizimi arasında inve :için karar verirken hangisinin daha az kafa karıştırıcı ve kullanıcılar için daha belirgin olduğunu düşünmeliyiz. Aşırı durum muhtemelen

for (in in in in())
for (in in : in())

(Not: Java, tür adları, değişkenler ve yöntemler için ayrı ad alanlarına sahiptir. Bunun çoğunlukla bir hata olduğunu düşünüyorum. Bu, daha sonra dil tasarımının daha fazla hata eklemesi gerektiği anlamına gelmez .)

Hangi alternatif, yineleme değişkeni ile yinelenen koleksiyon arasında daha net görsel ayrımlar sağlar? Koda baktığınızda hangi alternatif daha hızlı tanınabilir? Bu kriterler söz konusu olduğunda, sembolleri ayırmanın bir kelime dizisinden daha iyi olduğunu gördüm. Diğer diller farklı değerlere sahiptir. Örneğin, Python, birçok operatörü doğal olarak okunabilmeleri ve anlaşılması kolay olacak şekilde İngilizce olarak söyler, ancak aynı özellikler bir bakışta bir Python parçasını anlamayı zorlaştırabilir.


17

For-each döngü sözdizimi Java 5'te eklenmiştir. inBir dil anahtar sözcüğü oluşturmanız gerekir ve daha sonra bir dile anahtar sözcükler eklemek, mevcut kodu bozduğu için her ne pahasına olursa olsun kaçındığınız bir şeydir - aniden adlandırılan tüm değişkenler in ayrıştırmaya neden olur hata. enumbu konuda yeterince kötüydü.


2
Bu ... rahatsız edici görünüyor. Dil tasarımcılarının başlangıçtan itibaren gerekli anahtar kelimelerin çoğunu tahmin edecek kadar iyi olduğunu varsayar. Bunun bile gerekli olduğundan emin değilim; iyi derleyiciler, bir anahtar kelimenin içeriğine göre bir değişken olup olmadığını belirleyebilir.
Robert Harvey

2
Java C # gibi içeriksel anahtar kelimeler var sanmıyorum. Yani, kullanmak inya yeni bir anahtar kelime tanıtmak, böylece geriye dönük uyumluluğu ( System.in, herhangi biri?) Kırmak ya da daha önce bilinmeyen yepyeni bir kavramı (bağlamsal anahtar kelimeler) tanıtmak anlamına gelirdi . Hepsi ne için?
Jörg W Mittag

2
İçeriğe dayalı anahtar kelimelere ne zarar verir?
user2418306

5
@ user2418306 Bir anahtar kelime eklemek, dilin ayrı bir lexer aşamasıyla ayrıştırılmaması koşuluyla mevcut kodu kırmak zorunda değildir. Özellikle, for(variable in expression)“in”, değişkenler için “in” kullanılabilse bile, herhangi bir yasal kodla hiçbir zaman belirsiz olamaz. Bununla birlikte, ayrı bir sözlük aşaması birçok derleyici takım zincirinde oldukça yaygındır. Bu, bazı ortak ayrıştırıcı jeneratörleriyle Java'yı ayrıştırmayı imkansız veya en azından çok daha zor hale getirecektir. Bir dilin sözdizimini basit tutmak genellikle ilgili herkes için iyidir; herkesin C ++ veya Perl gibi sözdizimsel canavarlıklara ihtiyacı yoktur.
amon

1
@RobertHarvey: Unutmayın constve gotoher ikisi de Java'da ayrılmış kelimelerdir, ancak henüz kullanılmamıştır (henüz).
TMN
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.