Değişken isimleri neden sayılarla başlayamıyor?


136

Bir süre önce yeni bir C ++ geliştiricisiyle çalışıyordum, şu soruyu sordu: "Değişken isimleri neden sayılarla başlayamıyor?"

Bazı sayıların içinde metin olabileceği (123456L, 123456U) dışında bir cevap bulamadım ve derleyiciler bir miktar alfa karakterli her şeyin değişken adı olduğunu düşünseler bu mümkün olmazdı.

Doğru cevap bu muydu? Başka sebep var mı?

string 2BeOrNot2Be = "that is the question"; // Why won't this compile?

15
Ve neden içlerinde boşluk olamıyor?
Tim

4
Bu sorun, ilk makro derleyiciler için değilse bile, C ++ 'dan en az 20 yıl öncesine dayanmaktadır.
Ken Gentle

2
Peki, FORTH'da bunu yapabilirsiniz. AFAIK, 00'ı yığına iten bir kelime var . diğeri ise 0=0'ın yığında olup olmadığını kontrol etmesidir.
Ingo

12
Bu soru neden bu kadar popüler ve cevaplar bu kadar yanlış? Birçok dil değişkenlerin sayılarla başlamasına izin verir. C ++ bunu yapmaz, ancak belirli belirsizlikleri ortadan kaldıran uygun bir sınırlamadır. Bazen SO beni tüm yanlış şekillerde şaşırtıyor.
david.pfx

5
Bu soru bugün SO'da sorulmuşsa, görüşe dayalı olarak adlandırılacak ve kapanacaktır. Bunu sorduğun için teşekkürler.
Boon

Yanıtlar:


116

Çünkü o zaman bir rakam dizisi geçerli bir tanımlayıcı olduğu kadar geçerli bir sayı olacaktır.

int 17 = 497;
int 42 = 6 * 9;
String 1111 = "Totally text";

37
Peki ya değişkenlerin sadece sayı olamayacağını söyleselerdi. Sonra ne?
Pyrolistical

6
Sözcüğün bu kuralı kullanarak tanımlayıcıları alması için düzenli bir ifade bulmam daha uzun sürerdi, eğer mümkünse, bu yüzden neden hiçbir dilin bu şekilde uygulanmadığını anlayabiliyorum. diğer cevaplar.
skiphoppy

39
Sayılar + alfa olması gerekiyorsa, yine de String 0x123 = "Merhaba Dünya" yapabilirsiniz. Değişken adlarının "geçerli bir sayısal gösterime ayrıştırılmayan sayılar + alfa" olduğunu belirtmedikçe ve bu çok saçma.
eaolson

4
Derleyiciyi boşverin: Dili kullanan kişilerin değişken adlarını sayılardan kolayca (bir bakışta) ayırt edebilmesi gerekir. İlk karakter size söylemediyse - bunun yerine, kelimenin geri kalanında bir yerde sayısal olmayan bir alfa olup olmadığını anlamak için aramanız gerekirse - kodun okunması daha zor olurdu.
comingstorm

10
@eaolson: Ben ile başladı onaltılık sayılara bu kuralı uygulanan bir birleştirici ile çalıştık A- Fve ile sona erdi h. Bach'ın Two Part Invention # 13 (mantıksal ad? Bach) İçin müzik verilerine işaret edecek bir plak şirketi tanımlamaya çalıştığımda ilk kez beni şaşırttı .
supercat

116

Bunu bir düşünün:

int 2d = 42;
double a = 2d;

A nedir? 2.0? veya 42?

İpucu, anlamadıysanız, bir sayıdan sonra gelen d, ondan önceki sayı anlamına gelir.


11
Bu aslında [nispeten] geç gelen bir gösterimdir ("çift" için "d"), C89 standardı IIRC. Tanımlayıcılarda önde gelen sayısal değerler, bu yapı dilde ise mümkün değildir, ancak sayısalların bir tanımlayıcı başlatamamasının nedeni bu değildir.
Ken Gentle

1
dC ++ 'da geçerli bir kayan değişmez son ek değil. Kayan değişmez değerler varsayılan olarak çiftlerdir, kullanabilirsiniz fveya lbir kayan nokta veya uzun bir çift değişmez bilgiye ihtiyacınız varsa kullanabilirsiniz .
CB Bailey

1
Bu Java içindir ve asıl soru C ++ için olsa da, Java gibi diğer birçok dil için de geçerlidir. Ama katılıyorum. Tanımlayıcıların sayılarla başlayamamasının asıl nedeni bu değil.
Pyrolistical

50

Bu artık bir kongre, ancak teknik bir gereklilik olarak başladı.

Eski günlerde, FORTRAN veya BASIC gibi dillerin ayrıştırıcıları, boşluk kullanımını gerektirmiyordu. Yani temelde aşağıdakiler aynıdır:

10 V1=100
20 PRINT V1

ve

10V1=100
20PRINTV1

Şimdi sayısal öneklere izin verildiğini varsayalım. Bunu nasıl yorumlarsın?

101V=100

gibi

10 1V = 100

veya olarak

101 V = 100

veya olarak

1 01V = 100

Yani bu yasadışı hale getirildi.


1
Küçük nit: satır numaraları 1-6 arasındaki sütunlarda ve çalıştırılabilir kod 8. sütunun ardından olmalıdır. Öte yandan DO 10 I=1,50belirsiz bir şekilde DO1 0I=1,50[tesadüfen, virgül yerine nokta kullanırsa, ifade bir kayan noktalı değişken adlı DO10I.
supercat

İlginç açıklama! Bu eski diller için mantıklı, hala Python veya JavaScript veya R gibi diller için tasarım seçimine neden devam ettiğimizi merak etmeme neden oluyor.
Charles Clayton

Bunu BASIC ile kesinlikle hatırlıyorum ve bunun muhtemelen uygulamanın en geçerli pratik nedeni olduğunu hissediyorum. Teknik olarak yine de, aslında erken assembly diline dönebileceğini belli belirsiz hatırlıyorum. Aslının ne olduğundan emin değilim ve çok iyi yanılıyor olabilirim.
Brian Chandler

42

Çünkü derleme sırasında sözcüksel analizde geriye dönük takipten kaçınılır. Gibi bir değişken:

Apple;

derleyici, 'A' harfiyle karşılaştığında hemen bunun bir tanımlayıcı olduğunu bilecektir.

Ancak şöyle bir değişken:

123apple;

derleyici, 'a'ya ulaşana kadar bir sayı mı yoksa tanımlayıcı mı olduğuna karar veremez ve sonuç olarak geriye dönük izlemeye ihtiyaç duyar.


2
Derleyici tasarımları sınıfımı hatırlayarak cevaplamak için, Bu cevap doğrudur! Kudos
nehem

15

Derleyiciler / ayrıştırıcılar / sözcük çözümleyicileri benim için çok uzun zaman önceydi, ancak derleme birimindeki sayısal bir karakterin bir harfi mi yoksa bir tanımlayıcıyı mı temsil ettiğini açık bir şekilde belirlemede güçlük olduğunu hatırladığımı düşünüyorum.

Boşluğun önemsiz olduğu diller (doğru hatırlıyorsam ALGOL ve orijinal FORTRAN gibi) bu nedenle tanımlayıcılara başlamak için sayıları kabul edemezler.

Bu, depolamayı veya sayısal tabanı belirtmek için özel notasyonlardan önce geri gider.


9

Tanımlayıcıların bir rakamla başlamasına izin vermenin kullanışlı olacağını kabul ediyorum. Bir veya iki kişi, tanımlayıcınıza bir alt çizgi ekleyerek bu kısıtlamayı aşabileceğinizi söyledi, ancak bu gerçekten çirkin.

Bence sorunun bir kısmı, 0xdeadbeef gibi bir rakamla başlayabilen tanımlayıcılar için hatırlanması kolay kurallar bulmayı zorlaştıran sayı değişmezlerinden geliyor. Bunu yapmanın bir yolu, [A-Za-z _] + ile eşleşen ve bir anahtar kelime veya rakam OLMAYAN herhangi bir şeye izin vermek olabilir. Sorun, 0xdeadpork'a izin verilmesi gibi tuhaf şeylere yol açacak, ancak 0xdeadbeef'e izin verilmemesidir. Nihayetinde, tüm etlere adil davranmamız gerektiğini düşünüyorum: P.

C'yi ilk öğrenirken, değişken adlarının kurallarının keyfi ve kısıtlayıcı olduğunu hissettiğimi hatırlıyorum. Hepsinden kötüsü, hatırlamaları zordu, bu yüzden onları öğrenmeye çalışmaktan vazgeçtim. Sadece doğru olanı yaptım ve oldukça iyi çalıştı. Artık çok daha fazlasını öğrendiğime göre, o kadar da kötü görünmüyor ve sonunda doğru öğrenmeye başladım.


8
LOL - "Sorun şu ki, 0xdeadpork gibi garip şeylere izin verilmesine yol açacak, ancak 0xdeadbeef'e izin verilmeyecek. Nihayetinde, tüm etlere adil davranmamız gerektiğini düşünüyorum: P."
mr-euro

6

Muhtemelen birkaç nedenden dolayı alınmış bir karardır, jetonu ayrıştırırken, bunun bir tanımlayıcı mı yoksa değişmez mi olduğunu belirlemek için yalnızca ilk karaktere bakmanız ve ardından onu işlem için doğru işleve göndermeniz gerekir. Yani bu bir performans optimizasyonu.

Diğer seçenek, bunun birebir olup olmadığını kontrol etmek ve tanımlayıcıların alanını, evren eksi değişmez değerler olarak bırakmak olacaktır. Ancak bunu yapmak için, onu nasıl sınıflandıracağınızı bilmek için her simgenin her karakterini incelemeniz gerekir.

Ayrıca tanımlayıcıların anımsatıcı olması gereken biçimsel çıkarımlar da vardır, bu nedenle kelimelerin hatırlanması sayılardan çok daha kolaydır. Birçok orijinal dil, önümüzdeki birkaç on yıl için stilleri belirlerken yazılırken, "to" yerine "2" yi değiştirmeyi düşünmüyorlardı.


6

Değişken isimleri bir rakamla başlayamaz, çünkü aşağıdaki gibi bazı sorunlara neden olabilir:

int a = 2;
int 2 = 5;
int c = 2 * a; 

c'nin değeri nedir? 4 veya 10!

başka bir örnek:

float 5 = 25;
float b = 5.5;

ilk 5 bir sayı veya bir nesnedir (. operatörü). İkinci 5 ile benzer bir sorun var.

Belki başka sebepler vardır. Dolayısıyla, bir değişken adının başlangıcında herhangi bir rakam kullanmamalıyız.


Tanımlayıcıların en az bir rakam olmayan karakter içermesi gerekli olsa bile, harfleri içeren sayısal formatların da alfanümerik olmayan bir karakter içermesi gerekir [örneğin 0x1234'ün 1234 $ olarak yazılması ve 1E6'nın yazılması gerekir. 1.E6 veya 1.0E6 olarak] veya yasal ve yasadışı tanımlayıcı adlarının tuhaf bir kombinasyonuna sahip.
supercat

4

Bir değişken adına başlamak için bir rakamın kullanılması, derleme veya yorumlama sırasında hata kontrolünü çok daha karmaşık hale getirir.

Bir sayı gibi başlayan değişken adlarının kullanımına izin vermek, dil tasarımcıları için muhtemelen büyük sorunlara neden olacaktır. Kaynak kodu ayrıştırma sırasında, bir derleyici / yorumlayıcı, bir değişken adının beklendiği bir rakamla başlayan bir belirteçle karşılaştığında, belirtecin gerçekten bir değişken mi yoksa bir hata mı olduğunu belirlemek için çok büyük, karmaşık bir kurallar kümesini araştırması gerekirdi. . Dil ayrıştırıcısına eklenen karmaşıklık bu özelliği haklı çıkarmayabilir.

Hatırlayabildiğim kadarıyla (yaklaşık 40 yıl), değişken adlarına başlamak için bir rakam kullanımına izin veren bir dil kullandığımı hiç sanmıyorum. Bunun en az bir kez yapıldığına eminim. Belki, buradaki biri gerçekten bunu bir yerlerde görmüş.


1
O kadar zor değil. Sözcüksel aşamayı daha da zorlaştırır, hepsi bu. Elbette, derleyicileri aldığımda, sözcüksel taramanın toplam derleme süresinin dörtte birini alabileceği söylendi.
David Thornley

4

Birkaç kişinin fark ettiği gibi, değişken adlar için geçerli formatlar hakkında pek çok tarihsel bagaj vardır. Ve dil tasarımcıları her zaman yeni diller yaratırken bildiklerinden etkilenirler.

Bununla birlikte, bir dilin değişken adların sayılarla başlamasına izin vermediği çoğu zaman, bunların dil tasarımının kuralları olmasıdır. Çoğunlukla bunun nedeni, bu kadar basit bir kuralın dilin ayrıştırılmasını ve ifade edilmesini büyük ölçüde kolaylaştırmasıdır. Yine de tüm dil tasarımcıları bunun gerçek neden olduğunu bilmiyor. Modern sözcük oluşturma araçları yardımcı olur, çünkü eğer onu izin verilebilir olarak tanımlamaya çalışırsanız, size çelişkileri ayrıştıracaklardır.

OTOH, eğer diliniz değişken adlarını müjdelemek için benzersiz bir şekilde tanımlanabilir bir karaktere sahipse, bir sayı ile başlayacak şekilde ayarlamak mümkündür. Değişken adlarında boşluklara izin vermek için benzer kural varyasyonları da kullanılabilir. Ancak ortaya çıkan dil, muhtemelen herhangi bir popüler geleneksel dile pek benzemeyecektir.

Değişkenlerin sayılarla başlamasına ve gömülü boşluklara sahip olmasına izin veren oldukça basit bir HTML şablonlama dili örneği için Qompose'a bakın .


1
Aslında, tanımlayıcıları işaretleyen karakterlere sahip olmanıza izin veren birkaç dil vardır. Bunlar "sigil" olarak adlandırılır ve Perl ve PHP'de onlara sahipsiniz.
Jason Baker

Yine de PHP'de bir değişken adına bir sayı ile başlamanıza izin verilmemesi dışında - dil kuralları bunu yasaklar. :-) Ama aynı nedenle Qompose'da da yapabilirsiniz.
staticsan

4

Çünkü anahtar kelime ve tanımlayıcının sayısal karakterlerle başlamasına izin verdiyseniz, lexer (derleyicinin parçası) sayısal bir değişmezin başlangıcı ile bir anahtar kelimeyi çok daha karmaşık (ve daha yavaş) hale getirmeden kolayca ayırt edemezdi.


2
Sözcük oluşturma süreci nadiren darboğazdır. Elbette, tanımlayıcı jetonlar için normal ifadeyi daha karmaşık hale getirir, ancak yine de süper hızlı DFA'lar olabilirler. Bunların çalışma zamanı, derleyicilerin gerçekleştirmesi gereken diğer görevlerin çoğuna kıyasla fıstıklardır.

4

Kısıtlama keyfi. Çeşitli Lisp'ler, sembol adlarının rakamlarla başlamasına izin verir.



2

C ++ buna sahip olamaz çünkü dil tasarımcıları bunu bir kural haline getirdi. Kendi dilinizi yaratacak olsaydınız, kesinlikle buna izin verebilirdiniz, ancak muhtemelen onların yaptıkları aynı problemlerle karşılaşır ve buna izin vermemeye karar verirsiniz. Sorunlara neden olabilecek değişken adlarına örnekler:

0x, 2d, 5555


Bu kısıtlama, bu tür sözdizimine izin verilmeyen dillerde geçerlidir.
Jason Baker

2

Rahatlatıcı sözdizimsel geleneklerin temel sorunlarından biri, kodlama sürecine bilişsel uyumsuzluk getirmesidir. Kodunuz hakkında nasıl düşündüğünüz, bunun getireceği netlik eksikliğinden derinden etkilenebilir.

"Herhangi bir aracın en önemli yönü, kullanıcısı üzerindeki etkisidir" diyen Dykstra değil miydi?


1

Muhtemelen, insanın bir sayı mı yoksa bir tanımlayıcı mı olduğunu anlamasını ve geleneklerden dolayı kolaylaştırdığı için. Bir rakamla başlayabilen tanımlayıcılara sahip olmak, sözcüksel taramaları o kadar karmaşık hale getirmez.

Tüm dillerde bir rakamla başlayan yasak tanımlayıcılar yoktur. Dördüncüsü, sayı olabilirler ve küçük tamsayılar normalde Dördüncü sözcükler (esasen tanımlayıcılar) olarak tanımlanırdı, çünkü "2" yi yığının üzerine 2'yi bir sayı olarak tanımaktan daha hızlı bir rutin olarak okumaktı. Değeri 2 olan (programcıdan veya disk bloğundan gelen girdiyi işlerken, Forth sistemi girdiyi boşluklara göre bölerdi. Belirtecin tanımlanmış bir kelime olup olmadığını görmek için sözlükte belirteci yukarı bakmaya çalışırdı ve eğer onu bir sayıya çevirmeye çalışmazsa ve değilse bir hata işaret etmezse.)


Mesele şu ki, Forth gerçekten çok karmaşık bir ayrıştırıcıya sahip değil. Gerçekten, tek ilgilendiği şey, bir tanımlayıcının iki boşluk kümesi arasında olup olmadığıdır.
Jason Baker

1

Sembol adlarının sayılarla başlamasına izin verdiğinizi varsayalım. Şimdi bir değişken 12345foobar olarak adlandırmak istediğinizi varsayalım. Bunu 12345'ten nasıl ayırırsınız? Normal bir ifade ile yapmak aslında çok da zor değil. Sorun aslında performansla ilgili. Bunun neden çok ayrıntılı olduğunu gerçekten açıklayamam, ancak esasen 12345foobar'ı 12345'ten ayırmanın geri dönüşü gerektirdiği gerçeğine dayanıyor. Bu, normal ifadeyi deterministik olmayan yapar.

Burada bunun çok daha iyi bir açıklaması var .


1
İnsan nasıl adlı bir değişken izin için normal bir ifade tasarlamak istiyorum ifqya doublezama ifya double? Tanımlayıcıların rakamlarla başlamasına izin vermenin temel sorunu, tamamen alfanümerik karakterlerden oluşan onaltılık değişmez değerlerin ve kayan noktalı sayıların mevcut formlarının bulunmasıdır (diller, 0x1234 yerine 1234 $ veya h'1234 gibi bir şey kullanır ve aşağıdaki gibi sayılar gerektirir) 1Ç23 bir nokta eklemek, bu sorunu önleyebilir). C'yi regex-ayrıştırma girişimlerinin, gibi şeyler tarafından zaten tetiklenebileceğini unutmayın 0x12E+5.
supercat

1

Bir derleyicinin bir değişkeni sayı yerine bellek konumunda ASCII kullanarak tanımlaması kolaydır.


1

Derleyicinin aşağıdaki gibi 7 aşaması vardır:

  1. Sözcüksel analiz
  2. Sözdizimi Analizi
  3. Anlamsal Analiz
  4. Ara Kod Üretimi
  5. Kod Optimizasyonu
  6. Kod Üretimi
  7. Sembol Tablosu

Kod parçasını derlerken sözcük analizi aşamasında geriye dönük izleme önlenir. Apple gibi bir değişken olan derleyici, sözcüksel Analiz aşamasında 'A' harfiyle karşılaştığında bir tanımlayıcısını hemen bilecektir. Bununla birlikte, 123apple gibi bir değişken olan derleyici, 'a'ya ulaşana kadar onun bir sayı mı yoksa tanımlayıcı mı olduğuna karar veremez ve bunun bir değişken olduğunu belirlemek için sözcüksel analiz aşamasına geri dönmesi gerekir. Ancak derleyicide desteklenmez.

Belirteci ayrıştırırken, bunun bir tanımlayıcı mı yoksa değişmez mi olduğunu belirlemek için yalnızca ilk karaktere bakmanız ve ardından işlenmesi için doğru işleve göndermeniz gerekir. Yani bu bir performans optimizasyonu.


0

Bence basit cevap, bunu yapabilir, kısıtlama dil temelli. C ++ ve diğerlerinde bunu yapamaz çünkü dil onu desteklemiyor. Buna izin vermek için kurallara dahil edilmemiştir.

Soru, satrançta Kralın neden dört boşluk birden hareket ettiremediğini sormaya benzer. Bunun nedeni Satranç'ta yasadışı bir hareket olmasıdır. Elbette başka bir oyunda olabilir mi? Bu sadece oynanan kurallara bağlıdır.


C ++ 'ın son zamanlarda hala hayatta olan insanlar tarafından icat edilmesi dışında. Onlara neden yaptıklarını seçtiklerini ve alternatifleri reddettiklerini sorabiliriz. Aynı şey satranç için geçerli değil.
Steve Jessop

Ama yaptığım nokta bu değil. Değişken adlarının başında neden sayı olamayacağına dair bir benzetme ve en basit cevap, dilin kuralları buna izin vermediği için.
kemiller2002

Elbette, ama soruyu soranın bir embesil olduğunu sanmıyorum. Muhtemelen bu kadarını kendi başına halletmiştir. IMO sorusu "neden dilin kuralları buna izin vermiyor?" Kuralları bilmek ile anlamak arasındaki boşluğu doldurmak istiyor.
Steve Jessop

Evet, bunu düşündükten sonra nereye gittiğini anladım. Haklısın. Sanırım Occam'ın usturasını biraz özgürce uyguluyordum ve neden değişkenlerin sayılarla başlamaması dışında nedeninin gerçek bir cevabının olmadığını, çünkü sayıların olmadığını varsaydım.
kemiller2002

Yanlış olduğunu söylemiyorum, akıl, ara sıra C ++ standart organlarının kararları ölümlü anlayışı aşıyor ve sonunda "çünkü bir şeye karar vermeleri gerekiyordu ve buna karar verdiler". Ama orada sorulacak en azından bir soru var :-)
Steve Jessop

0

Başlangıçta basitçe, değişken isimlerini sayılardan ziyade dizeler olarak hatırlamanın daha kolay olduğu için (daha fazla anlam verebilirsiniz), ancak dizenin anlamını geliştirmek veya aynı değişken adının kullanılmasına izin vermek için sayılar dizeye dahil edilebilir ancak ayrı, ancak yakın bir anlama veya bağlama sahip olarak belirlenmiş mi? Örneğin döngü1, döngü2 vb. Her zaman bir döngüde olduğunuzu ve / veya döngü 2'nin döngü1 içinde bir döngü olduğunu bilmenizi sağlar. Değişken olarak hangisini tercih edersiniz (daha fazla anlamı vardır): adres mi yoksa 1121298 mi? Hangisini hatırlaması daha kolay? Bununla birlikte, eğer dil sadece metin veya sayıları ($ in $ adresi gibi) belirtmek için bir şey kullanıyorsa, derleyiciye takip eden şeyin bir değişken olarak ele alınacağını söyleyeceği için gerçekten bir fark yaratmamalıdır ( bu durumda).


0

Değişken, derleyici tarafından derleme sırasında da bir değer olarak düşünülebilir, böylece değer, değeri tekrar tekrar yinelemeli olarak çağırabilir


0

Kod parçasını derlerken sözcük analizi aşamasında geriye dönük izleme önlenir . Apple gibi değişken; , derleyici, sözcük analizi aşamasında 'A' harfiyle karşılaştığında onun bir tanımlayıcısını hemen bilecektir. Ancak 123apple gibi bir değişken; , derleyici, 'a'ya ulaşana kadar bir sayı mı yoksa tanımlayıcı mı olduğuna karar veremez ve bunun bir değişken olduğunu belirlemek için sözcüksel analiz aşamasına geçmek için geriye doğru izlenmesi gerekir. Ancak derleyicide desteklenmez.

Referans


0

Değişken bildirmeye geldiğinde bunda yanlış bir şey olamaz. Ama bu değişkeni başka bir yerde kullanmaya çalıştığında bazı belirsizlikler var:

let 1 = "Merhaba dünya!" baskı (1) baskı (1)

print, tüm değişken türlerini kabul eden genel bir yöntemdir. bu durumda derleyici, programcının hangisine (1) atıfta bulunduğunu bilmez: tamsayı değerinin 1'i veya bir dize değerini saklayan 1. Bu durumda derleyicinin böyle bir şeyi tanımlamasına izin vermesi belki daha iyi olabilir, ancak bu belirsiz şeyleri kullanmaya çalışırken, bu hatayı nasıl düzelteceğine ve bu belirsizliği nasıl gidereceğine dair düzeltme yeteneği olan bir hata getirin.

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.