Tanımlayıcılar neden bir rakamla başlamamalı?


32

Çoğu programlama dilinin, bir sayı ile başlayan bir tanımlayıcı bildirmesine izin vermeyecek şekilde tasarlandığı görülmektedir. Sebebini bilmek sadece merak ettim. Web'i zaten aradım, ancak tatmin edici bir açıklama bulamadım.


4
Netlik ve okunabilirlik için fayda sağlayacağı değişken bir isim için tek bir örneğiniz var mı?
Güvenli

5
@Secure: 3dspline, 4seasonPizza, 2pdfConverter, 8bitInt, ...
kullanıcı bilinmeyen

6
Forth izin verir. Yerleşiklerin: 2DUP, 2DROP, 2SWAP, 2> R, 2R @, 2R>, 0 =, vb.
Peter Mortensen,

TCL'de olduğu gibi, ancak standart TCL komutlarının hiçbirinin bir sayı
jk

1
SO'da

Yanıtlar:


51

C / C ++ 'da, bir harf tarafından takip edilen bir sayının sayısal bir sabit olduğu düşünülür ve ardından gelen dize, sabitin türünü nitelendirir. Örneğin (bunlar VC ++, ne kadar standart olduklarından emin değilsiniz):

  • 0 - işaretli tam sayı
  • 0l - imzalı uzun tamsayı
  • 0u - işaretsiz tam sayı
  • 0i64 - 64 bit işaretli tam sayı

Bu yüzden a) Daniel'in söylediği gibi lexer için daha kolay ancak b) 0y değişken olabileceğinden ancak 0u asla olamayacağı için açık bir ayrım yapar . Ayrıca "i64" gibi diğer niteleyiciler "l" veya "u" den çok daha sonra eklenmiş ve gerektiğinde daha fazla ekleme seçeneğini açık tutmak istemektedir.


7
ayrıca, onaltılık sayılar 0xd + biçiminde yazılır, burada d + 1 daha onaltılık hane 0-f'dir - yani 0xbeef tamamen geçerli bir "sayı" dır.
tcrosley

20
siz çocuklar bir dil spikeri için gitmeyeceğimin farkındaydınız, ancak konuyu açıklamak için sadece birkaç örnek verdiniz, değil mi?
DXM

6
Re: "gerekirse daha fazla ekleme seçeneğini açık tutmak istiyorlar": Ve C ++ 11 bile kendi eklemenizi sağlar; bkz http://en.wikipedia.org/wiki/C++11#User-defined_literals .
ruakh

2
Bunun doğru açıklama olduğunu sanmıyorum. "Tanıtıcı bir rakam ile başlayamaz" kuralı Algol, Pascal ve alfabetik soneklerin sayısal sabitlere izin vermeyen diğer dilleri için geçerlidir.
Larry Gritz

1
@LarryGritz: "Kelimelerin boşluklarla tutarlı bir şekilde ayrılması, MS 10. yüzyılda genel bir gelenek haline geldi ve FORTRAN'ın uygulamayı terk ettiği yaklaşık 1957 yılına kadar sürdü." —Sun FORTRAN Referans Kılavuzu (wiki'den). Fortran'ın kendine özgü nedenleri vardı, çünkü genel olarak yerlerin isteğe bağlı olduğuna karar verdiler. MODERN dilleri boşlukları gibi. Algol ile kendi başınızasınız ama ben de bu kadar modern değilim. Öte yandan, C / C ++ / C # / F # hepsinin ekleri var.
DXM

49

Lexer'ı uygulayan insanların rahatlığı. (Hayır, cidden, bununla ilgili. Çeşitli dillerin başka nedenleri var, ama sonuçta buna bağlı.)


2
PEG'leri veya diğer modern ayrıştırma tekniklerini kullanarak tümleşik hazırlayıcılar ve rakamlarla başlayan tanımlayıcılar arasında ayrım yapmak kolay olacaktır. İlkel sözcükleri kullanan derleyiciler bile bunları aynı belirteç kategorisine koyabilir ve daha sonra ayırt edebilir. Örneğin 0fludeğişmez ve 0gluyerel bir tanımlayıcı olsaydı çok garip olurdu .
Daniel Lubarov

2
İnsanların onları ayırt etmesi kesinlikle mümkün . Karar, teknik şartlardan ziyade rahatlığa (veya daha az yardımseverseniz tembellik) dayanarak verilir.
Daniel Pittman

2
@DanielPittman: Her türlü güvenilir belirsizliği gidermek için anlamsal analize ihtiyacınız olacak, bu yüzden lexer'da yapılamaz. Kararı lexer'in dışına itmek, çözümleyiciyi daha karmaşık hale getirir ve ne yararı olur? Çok düşük maliyet / fayda durumunun yanı sıra, böyle bir olayı ele almanın iyi bir yolu yoktur int 0u = 5; unsigned int x = 0u;Ancak bu kodun yorumunu tanımlamayı seçtiniz (muhtemelen x == 0 veya x == 5), insanların kafası karışacak belirsizlik yüzünden. Derleyiciyi bu şekilde uygulamak önemsiz olsa da, iyi bir tasarımcı muhtemelen yapmazdı.
Joren

10
Başlıca kolaylık kafamdaki ayrıştırıcı içindir, dilin yaratıcısı için değildir.
CodesInChaos

2
Sözcük analizinin genellikle bir derleyicinin / tercümanın en yavaş aşaması olarak büyük bir faktör olduğunu öğrenmek birçok insan için hala şaşırtıcı.
hippietrail

20

Aşağıdaki 2 durumu göz önünde bulundurun:

Dava 1

Bir tanımlayıcının bir sayı ile başlayabileceğini varsayalım.

Dolayısıyla, aşağıdaki gibi bir ifade geçerli olur (bir tanımlayıcı 1 veya daha fazla karakter içerebildiğinden):

int 3;

Yukarıdaki değişkeni bir programda kullanmaya çalıştığımda, derleyici belirsizliğine neden olur:

int 3, a;
3 = 5;
a = 3;

İfadede a=33'ün rolü nedir (5 değerine sahip bir değişken mi yoksa 3 rakamı mı)?

Durum 2

Yukarıdaki örneğe zıt olarak, bir dilin gerçekte tanımlayıcı olarak kullanılmasına rağmen sayıları reddederken sayı ile başlayan tanımlayıcılara izin vermek olduğunu varsayalım. Bu, aşağıdaki sorunlara neden olabilir:

  • Bir değişkenin 1 veya daha fazla karakterden oluşabileceğini söyleyen değişkene ilişkin dil kuralları, aşağıdaki gibi karmaşık bir kural için yeniden tanımlanmalıdır: Bir değişken, bir veya daha fazla karaktere sahip olabilir ve bir sayı ile başlamazsa, benzersiz olması gerekir. Sayı ile başlarken tek karakter uzunluğunda olamaz (vb.)

  • Derleyici tüm sayılar (örneğin 333) ve geçerli alfabe sonekleri (örneğin 34L) değişken isimleri olarak kullanıldığında hata durumlarını kontrol etmek ve raporlamak zorunda kalacaktır. Python ve JS gibi gevşek olarak yazılan ve değişkenleri anında bildirmeden kullanabileceğiniz değişkenleri yazarken, örneğin tüm sayıları içeren özel durumları kontrol etmek bile imkansız if (33==5)olabilir. Ancak derleyici bunu tanımlayamaz ve hatayı rapor edemez.

Bu kısıtlamanın yapılması, programcının numaraları tanımlayıcı adları olarak kullanmasını önleyecektir.


2
Bu mantığa göre, tanımlayıcılar, anahtar kelimeler için belirsiz oldukları için karakter içeremez. Ne kadar felaket int char = floatolacağını hayal edebiliyor musun?
Pubby

4
@Pubby: Söylediklerimi, henüz tam olarak anlayamadığım bir anlam ifade etmeden nasıl tahmin edebileceğini anlamıyorum. Yorumunuz ne anlama geliyor?
aml90,

Soruyu kelimenin tam anlamıyla çok fazla aldığınızı ve lexing önceliğini kullanarak hiçbir şekilde belirsiz olmadığını söylüyorum. Örneğin, derleyici intbir anahtar kelime değil bir tanımlayıcı olduğunu nasıl biliyor ? Şey, intaynı sayısal sözlerin sahip olacağı gibi daha yüksek önceliğe sahip.
Pubby

@Pubby: Belirsizliğe göre, derleyicinin değişken adını hangi bağlamda kullandığımı bilmeyeceğini kastediyordum (sözlük önceliği bile olsa). Örneğin, şu kodu göz önünde bulundurun: int 3,a; 3=5; a=3; a = 3 ifadesinde, 3 tanımlayıcı mı yoksa bir sayı olarak mı yorumlanır? Bu belirsizliğe neden olur. Umarım açıktır.
aml 90

2
Ayrıca bu argümanı zayıf buluyorum. Başlayan ancak tamamıyla rakamlardan oluşmayan tanımlayıcıları kabul edecek bir sözcü yazmak önemsizdir.
Larry Gritz

11

Çoğu zaman bunun derleyici yazarlar için ayrıştırma verimliliğini ve ayrıştırma verimliliğini kolaylaştırmakla alakası yoktur, ancak daha net ve okunaklı ve açık kodları teşvik eden bir sözdizimi tasarlamakla daha fazla ilgisi yoktur.

Dil tasarımcıları, sadece 1 numara gibi nümerik harfleri sadece düz 1 olarak yazmanın iyi olacağını düşündüler .

Sayısal hazırlayıcıların bir şekilde örneğin tildas olarak yazıldığı bir dil sözdizimi tasarlamak oldukça mümkün olabilir, bu sayede bir numaralı sayısal hazırlayıcı ~ 1 ~ olarak kodlandı ve bir anahtar sözcük içermeyen ve tırnak içine alınmayan herhangi bir şey değişken bir ad olarak değerlendirildi .

Böylece aşağıdaki gibi kodları kodlayabilirsiniz:

1 = ~2~
two = 1 * ~2~

Ayrıca:

2 = ~3~
six = 2 + 2

Seçtiğiniz ve belirsiz ve takip etmek zor zor sözdizimi ne olursa olsun kaçınılmazdır.

C dili ve "kıvrımlı parantez" dillerinin çoğu, C'den gelen dilbilgisi programcılarının doğrudan Octal ve Onaltılık değişmezleri kodlamasını ve bunun önemini belirtmişse değişmezin türünü belirtmesini sağlamanın iyi bir fikir olduğunu düşünüyordu. Yani

010  // Octal 10 = 8;
0x10 // Hexadecimal 10 = 16;
5l   // long integer with decimal value 5
2.0d // double float with value 2

Bu yüzden değişken isimlerine izin vermiş olsanız bile, en az bir harf içeren bir rakam ve harf kombinasyonunu izleyen bir rakamla başlasanız bile, programcıya belirli bir grubun değişken bir isim mi yoksa sayısal bir değişmez mi oluşturduğuna karar verme problemini sunarsınız.

2lll = 22 // OK
2ll  = 2  // compiler error

Bu belirsizlik, program yazarken veya okurken hiç kimseye yardımcı olmaz.

Yakından ilgili bir gerçek dünya örneği için, tasarımcıları anahtar kelimeleri değişken adlar olarak kullanmanın iyi bir fikir olduğunu düşünen PL / 1 diline bakabilirsiniz ki:

IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
IF IF THEN ELSE = IF; ELSE THEN = ELSE;
DO WHILE (WHILE = DO); END = WHILE + DO; END;

Derleyen ve yürüten geçerli bir koddur.


C, Unix için portatif montaj olarak tasarlandı. Unix aslen 18 bitlik bir makine için tasarlanmıştı; octal aynı şekilde yazdırmak için uygun, hex'in 8/16/32 bitlik makine değerlerini yazdırmak için de uygun. Bu yüzden aslında sekizlik ihtiyaçları vardı.

Ayrıca bit bükme (OR, XOR, AND, NOT) ve aygıt sürücülerini uygulamak için, değerin yanı sıra değişmezin tam boyutunu belirlemek de önemlidir!
James Anderson

10

Fortran'ın daha sonra dillerin nasıl tasarlandığı üzerinde çok büyük bir etkisi oldu. Daha önceleri (bu problemlerin bazıları giderildi) Fortran, bir tanımlayıcıya hangi ismi verebileceğinizi kısıtlayan neredeyse hiçbir kurala sahip değildi. Bu dilin hem derleyiciler hem de programcılar için ayrıştırılması son derece zor oldu. İşte klasik bir örnek:

if if .eq. then then = else else else = endif endif
K  I   K   K    I      I    K    I      I     K

Burada "dil anahtar kelimeleri" K ve tanımlayıcıları (değişken isimleri) ile işaretledim. İmla konusunda hiçbir fark olmadığı göz önüne alındığında, bunun ne kadar kafa karıştırıcı olabileceğini muhtemelen anlayabileceğinizi düşünüyorum. Elbette, bu aşırı bir örnektir ve bilerek böyle bir kod yazan hiç kimsenin olasılığı düşüktür. Bazen insanlar yaptılar ve basit bir yazım hatası dil spec o hiç tasarlanmamış olsa bile, bu şekilde ayrıştırılması gerektiğini söyledi kod neden olabilecek durumlar bir çok - gerçi tanımlayıcı adları için "geri dönüşüm" dil anahtar kelimeleri. Tanınmış başka bir örnek için, bunu karşılaştırın:

do 10 i = 1,10

buna:

do 10 i = 1.10

İlki bir do döngüsüdür - 10 kez kod bloğunu tekrar eder. Ancak ikincisi, virgülün ondalık bir noktaya dönüşmesini sağladı, bu yüzden değeri 1.10bir değişkene atadı do 10 i.

Bu aynı zamanda bir Fortran ayrıştırıcı yazmanın göreceli olarak zor olduğu anlamına geliyordu - dohattın başlangıcında satırın sonuna gelinceye kadar gerçekten anahtar bir kelime olduğundan emin olamazdınız ve dodöngü mevcuttu. Ayrıştırıcı, genellikle, gerçekte orada olanın "doğru" (ancak genellikle istenmeyen) cevabına gelmek için çizgiyi yeniden başlayarak yeniden parçalamaya hazır olmak zorundaydı.

Bundan birkaç yıl sonra, dil tasarımcıları (çoğu zaten) ters uç noktaya yöneldi - kullanıcılar hakkında çok fazla şikayet etmeden, dil hakkında neredeyse her şeyi mümkün olduğu kadar kısıtlamak .

Erken TEMEL, örneğin, temelde bile bir anahtar kelime kullanmayın söyledi kısmının bir tanımlayıcı - örneğin, fora=1olarak çözümlenen for a = 1(yani bir başlangıcı fordöngü, değil bir atama). Görünüşe göre bu çok uzun sürmeyecek kadar şikayet üretti. Rakamla bir tanımlayıcıyı başlatmayla ilgili kural, görünüşte çok fazla şikayet üretmedi, bu yüzden kullanılmaya devam ediyor (en azından çoğu dilde).


IMHO bu gerçek akla yakın. Fortran gibi erken diller, bazı yönlerden çok yapılandırılmamış, sağlam derleyiciler yazmakta zorluk çekmeye ve insanların kaynak kodunu görsel olarak ayrıştırmada zorluğa yol açıyordu. "Do10i = ..." klasik ve ünlü bir örnektir. Diller geliştikçe, bazı kurallar daraltıldı. Algol, muhtemelen "tanımlayıcılar harflerle başlar ve daha sonra harf veya rakamlara sahip olabilir" standardının büyük babasıdır.
Larry Gritz

BASIC'in (Applesoft Basic ve Commodore Basic dahil) en popüler Mikrobilgisayar sürümlerinin temelini oluşturan Microsoft BASIC yorumlayıcısı olan FYI, bir dil belirtecini yüksek bit setiyle eşleşen herhangi bir karakter dizisini dönüştürmek için açgözlü bir belirteç kullandı. Bu herhangi bir sözdizimsel analiz olmadan yapıldı. Ardından, programı çalıştırırken, tercüman bulduğu harfleri değişken adının bir parçası olarak kabul eder.
supercat

1

Muhtemelen bu sözleşme çok eski tarihsel dil tasarım kararlarından evrimleşmiştir, eski makinelerde, sözlüksel analiz de dahil olmak üzere tüm derleyicinin bir kaç kelimede çalışması gerekiyordu, mevcut mobil cihazlarda ilk seviye işlemci veri önbelleğinden bile daha az bellek vardı. bu yüzden izin verilen değişken isimleri çok sınırlıydı ve çok az sayıda op kodda sayısal sabitlerden ayırt edilmesi kolay olmalıydı.

Böylece, kongre programcı nesiller için kullanılan kuşak haline geldi.


1

Programlama dili için mantıklı bir kural değil, yalnızca birçok dil tasarımcısı tarafından kullanılan kuraldır.

Tanımlayıcılar için tüm karakterlere izin veren kökten farklı bir dil tasarlayabilirim. Tüm kod satırları için ilk 20 karakter ifade tipini tanımlayacaktır, ardından sonraki 20 karakter ifade için ilk sembolü tanımlayacak ve sonraki 20 karakter ifade için operand olacaktır. Bu dil bir yığın işlemcide yürütülecektir.

01234567890123456789 01234567890123456789 01234567890123456789

decl symbol          12345                
assign value         12345                12345
decl symbol          99999                
assign value         99999                12345
push                 12345
push                 99999
add
print top

Bu kod aşağıdaki gibi C dilinde çevrilebilir:

int i12345 = 12345;
int i99999 = 12345;
printf("%d", i12345+i9999);

Bu kadar. Bu anlamsız ve tanımlayıcıların sayısız kuralı da mantıklı temelde anlamsız.


0

"Lexer için kolaylık" ek olarak, aynı zamanda "okuyucu için kolaylık" dikkate alarak değer olduğunu düşünüyorum.

Kod okurken, hangi kelimelerin tanımlayıcı olduğunu ve hangilerinin rakam olduğunu hızlı ve tekrar tekrar tanımlamanız gerekir. Görsel desen eşleştirmemizde başlangıçta rakam aramak daha kolaydır; emin olmak için tüm karakterleri dikkatlice kontrol etmemiz gerekirse bir angarya olurdu.


0

Bu sorunun cevabı, normal ifadeyi tanımlayan otomatlarda veya daha kesin olarak sonlu otomatlardadır. Kural şudur: derleyiciler, ayrıştırdıkları her karakterde karar vermek için kesin algoritmalara veya kurallara ihtiyaç duyarlar. Eğer tanımlayıcılar bir sayıyla başlamaya izin verilseydi, derleyici düzeltilmiş olur ... gelenin niteliği hakkında ... bir sayı mı yoksa bir tanımlayıcı mı olur ... ve derleyiciler olarak önceki konumlara geri dönemez. .so .. derleyiciye yaklaşmakta olan belirtecin tam olarak bir tanımlayıcı veya bir sayı olduğunu açıkça belirtmek için ... bu kısıtlama var ... bu kodun ... derleyici sadece gelen belirteci ilk karakteri tarayarak bilir bir tanımlayıcı veya sayıdır.

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.