Mengapa nama variabel tidak dapat dimulai dengan angka?

136

Saya bekerja dengan pengembang C ++ baru beberapa waktu lalu ketika dia mengajukan pertanyaan: "Mengapa nama variabel tidak bisa dimulai dengan angka?"

Saya tidak dapat menemukan jawaban kecuali bahwa beberapa angka dapat memiliki teks di dalamnya (123456L, 123456U) dan itu tidak akan mungkin terjadi jika kompiler memikirkan segala sesuatu dengan sejumlah karakter alfa adalah nama variabel.

Apakah itu jawaban yang benar? Apakah ada alasan lain?

string 2BeOrNot2Be = "that is the question"; // Why won't this compile?
Yeremia
sumber
15
Dan mengapa mereka tidak memiliki ruang di dalamnya?
Tim
4
Masalah ini mendahului C ++ setidaknya 20 tahun, jika tidak kembali ke perakit makro pertama.
Ken Gentle
2
Nah, di FORTH, Anda bisa melakukannya. AFAIK, ada kata yang disebut 0yang mendorong 0 ke tumpukan. satu lagi adalah 0=yang memeriksa apakah 0 ada di stack.
Ingo
12
Mengapa pertanyaan ini begitu populer dan jawabannya salah? Banyak bahasa memungkinkan variabel untuk memulai dengan angka. C ++ tidak tetapi itu hanya batasan nyaman yang menghindari ambiguitas tertentu. Terkadang SO membuatku takjub dengan semua cara yang salah.
david.pfx
5
Jika pertanyaan ini diajukan hari ini di SO, itu akan disebut berdasarkan pendapat dan ditutup. Terima kasih telah menanyakan ini.
Boon

Jawaban:

116

Karena dengan demikian serangkaian digit akan menjadi pengidentifikasi yang valid serta nomor yang valid.

int 17 = 497;
int 42 = 6 * 9;
String 1111 = "Totally text";
skiphoppy
sumber
37
Nah, bagaimana jika mereka mengatakan variabel tidak bisa hanya angka. Lalu apa?
Pirolistik
6
Butuh waktu lebih lama untuk membuat ekspresi reguler bagi lexer untuk mengambil pengidentifikasi menggunakan aturan itu, jika itu mungkin, jadi saya bisa melihat mengapa tidak ada bahasa yang pernah diterapkan dengan cara itu, selain alasan yang diberikan dalam jawaban lain
skiphoppy
39
Jika itu harus angka + alpha, maka Anda masih bisa melakukan String 0x123 = "Hello World". Kecuali Anda menyatakan bahwa nama variabel adalah "angka + alfa yang tidak diuraikan ke penunjukan numerik yang valid", dan itu hanya konyol.
eaolson
4
Jangankan kompiler: orang yang menggunakan bahasa harus dapat dengan mudah (sekilas) membedakan nama variabel dari angka. Jika karakter pertama tidak memberi tahu Anda - sebaliknya, jika Anda perlu mencari melalui sisa kata untuk mengetahui apakah ada alpha non-numerik di suatu tempat di sana - kode akan lebih sulit untuk dibaca.
badai
10
@eaolson: Saya telah bekerja dengan assembler yang menerapkan aturan itu ke nomor hex yang dimulai dengan A- Fdan diakhiri dengan h. Membuatku tersandung saat pertama kali aku mencoba mendefinisikan label untuk menunjukkan data musik untuk Two Part Invention # 13 Bach (nama logis? Bach).
supercat
116

Nah pikirkan tentang ini:

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

Apa itu 2.0? atau 42?

Petunjuk, jika Anda tidak mendapatkannya, d setelah angka berarti angka sebelum itu adalah literal ganda

Pirolistik
sumber
11
Ini sebenarnya adalah notasi [relatif] terlambat datang ("d" untuk "ganda"), standar IIRC C89. Memimpin angka dalam pengidentifikasi tidak mungkin jika konstruk ini dalam bahasa, tapi itu bukan alasan angka tidak dapat memulai pengidentifikasi.
Ken Gentle
1
dbukan sufiks literal mengambang yang valid di C ++. Liter mengambang adalah ganda secara default, Anda dapat menggunakan fatau ljika Anda membutuhkan float atau literal ganda yang panjang.
CB Bailey
1
Ini untuk Java, dan sementara pertanyaan aslinya adalah untuk C ++, itu juga berlaku untuk banyak bahasa lain, seperti Java. Tapi saya setuju. Ini bukan alasan asli mengapa pengidentifikasi tidak dapat memulai dengan angka.
Pyrolistic
50

Ini adalah konvensi sekarang, tetapi dimulai sebagai persyaratan teknis.

Di masa lalu, parser bahasa seperti FORTRAN atau BASIC tidak memerlukan penggunaan spasi. Jadi, pada dasarnya, berikut ini identik:

10 V1=100
20 PRINT V1

dan

10V1=100
20PRINTV1

Sekarang anggaplah bahwa awalan angka diizinkan. Bagaimana Anda menafsirkan ini?

101V=100

sebagai

10 1V = 100

atau sebagai

101 V = 100

atau sebagai

1 01V = 100

Jadi, ini dibuat ilegal.

Roy Dictus
sumber
1
Nit kecil: nomor baris harus dalam kolom 1-6, dan kode yang dapat dieksekusi mengikuti kolom 8. Di sisi lain DO 10 I=1,50dapat diuraikan secara ambigu sebagai DO1 0I=1,50[secara kebetulan, jika seseorang menggunakan periode alih-alih koma, pernyataan tersebut menjadi tugas untuk variabel floating-point bernama DO10I.
supercat
Penjelasan menarik! Itu masuk akal untuk bahasa yang lebih lama, masih membuat saya bertanya-tanya mengapa kami masih melanjutkan pilihan desain untuk bahasa seperti Python atau JavaScript atau R.
Charles Clayton
Saya pasti ingat ini dengan BASIC dan merasa ini mungkin alasan praktis yang paling valid dari praktik ini. Namun secara teknis, saya samar-samar ingat bahwa mungkin sebenarnya kembali ke bahasa assembly awal. Saya tidak yakin apa assembler, dan saya sangat mungkin salah.
Brian Chandler
42

Karena backtracking dihindari dalam analisis leksikal saat kompilasi. Variabel seperti:

Apple;

kompiler akan segera tahu bahwa itu adalah pengidentifikasi ketika memenuhi huruf 'A'.

Namun variabel seperti:

123apple;

kompiler tidak akan dapat memutuskan apakah itu angka atau pengidentifikasi hingga mencapai 'a', dan sebagai hasilnya perlu dilakukan penelusuran ulang.

Jiayang
sumber
2
Untuk menjawab dengan mengingat kelas desain kompiler saya, jawaban ini benar! Kudos
nehem
15

Kompiler / pengurai / analisis leksikal sudah lama sekali bagi saya, tapi saya pikir saya ingat ada kesulitan dalam menentukan apakah karakter numerik dalam unit kompilasi mewakili literal atau pengidentifikasi.

Bahasa di mana ruang tidak signifikan (seperti ALGOL dan FORTRAN asli jika saya ingat dengan benar) tidak dapat menerima angka untuk memulai pengidentifikasi karena alasan itu.

Ini berjalan mundur - sebelum notasi khusus untuk menunjukkan penyimpanan atau basis numerik.

Ken Gentle
sumber
9

Saya setuju akan mudah untuk memungkinkan pengidentifikasi dimulai dengan angka. Satu atau dua orang telah menyebutkan bahwa Anda dapat mengatasi pembatasan ini dengan menambahkan garis bawah pada pengenal Anda, tetapi itu benar-benar jelek.

Saya pikir bagian dari masalah berasal dari sejumlah literal seperti 0xdeadbeef, yang membuatnya sulit untuk membuat aturan yang mudah diingat untuk pengidentifikasi yang dapat dimulai dengan angka. Salah satu cara untuk melakukannya mungkin dengan mengizinkan apa pun yang cocok dengan [A-Za-z _] + yang BUKAN kata kunci atau angka literal. Masalahnya adalah itu akan menyebabkan hal-hal aneh seperti 0xdeadpork diizinkan, tetapi tidak 0xdeadbeef. Pada akhirnya, saya pikir kita harus adil terhadap semua daging: P.

Ketika saya pertama kali belajar C, saya ingat merasa aturan untuk nama-nama variabel sewenang-wenang dan terbatas. Terburuk dari semuanya, mereka sulit untuk diingat, jadi saya menyerah mencoba mempelajarinya. Saya hanya melakukan apa yang terasa benar, dan itu bekerja dengan cukup baik. Sekarang saya sudah belajar banyak, sepertinya tidak terlalu buruk, dan akhirnya saya bisa mempelajarinya dengan benar.

semua kode Anda
sumber
8
LOL - "Masalahnya adalah hal itu akan mengarah pada hal-hal aneh seperti 0xdeadpork diizinkan, tetapi tidak 0xdeadbeef. Pada akhirnya, saya pikir kita harus adil terhadap semua daging: P."
mr-euro
6

Kemungkinan itu adalah keputusan yang datang karena beberapa alasan, ketika Anda menguraikan token, Anda hanya perlu melihat karakter pertama untuk menentukan apakah itu pengenal atau literal dan kemudian mengirimkannya ke fungsi yang benar untuk diproses. Jadi itu optimasi kinerja.

Pilihan lainnya adalah untuk memeriksa apakah itu bukan literal dan meninggalkan domain pengidentifikasi untuk menjadi alam semesta dikurangi literal. Tetapi untuk melakukan ini, Anda harus memeriksa setiap karakter dari setiap token untuk mengetahui cara mengklasifikasikannya.

Ada juga pengidentifikasi implikasi gaya yang seharusnya mnemonik sehingga kata-kata jauh lebih mudah diingat daripada angka. Ketika banyak bahasa asli sedang ditulis menetapkan gaya untuk beberapa dekade ke depan mereka tidak berpikir tentang mengganti "2" untuk "ke".

William
sumber
6

Nama variabel tidak dapat dimulai dengan angka, karena dapat menyebabkan beberapa masalah seperti di bawah ini:

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

berapa nilai c? adalah 4, atau 10!

contoh lain:

float 5 = 25;
float b = 5.5;

5 angka pertama, atau objek (operator). Ada masalah yang sama dengan 5 kedua.

Mungkin ada beberapa alasan lain. Jadi, kita tidak boleh menggunakan digit apa pun di awal nama variabel.

sbagdat
sumber
Bahkan jika seseorang mengharuskan pengidentifikasi mengandung setidaknya satu karakter non-digit, kita juga harus mengharuskan bahwa format numerik yang berisi huruf juga harus mengandung karakter non-alfanumerik [misalnya memerlukan 0x1234 ditulis sebagai $ 1234 dan 1E6 ditulis sebagai 1.E6 atau 1.0E6] atau memiliki kombinasi aneh dari nama pengidentifikasi legal dan ilegal.
supercat
4

Penggunaan digit untuk memulai nama variabel membuat pengecekan kesalahan selama kompilasi atau interpertasi jauh lebih rumit.

Mengizinkan penggunaan nama variabel yang dimulai seperti angka mungkin akan menyebabkan masalah besar bagi perancang bahasa. Selama parsing kode sumber, setiap kali kompiler / juru bahasa menemui token yang dimulai dengan digit di mana nama variabel diharapkan, itu harus mencari melalui serangkaian besar, aturan rumit untuk menentukan apakah token itu benar-benar variabel, atau kesalahan . Kompleksitas tambahan yang ditambahkan ke parser bahasa mungkin tidak membenarkan fitur ini.

Sejauh yang saya ingat (sekitar 40 tahun), saya tidak berpikir bahwa saya pernah menggunakan bahasa yang memungkinkan penggunaan digit untuk memulai nama variabel. Saya yakin ini dilakukan setidaknya sekali. Mungkin, seseorang di sini benar-benar melihat ini di suatu tempat.

mkClark
sumber
1
Itu tidak sulit. Itu membuat fase leksikal lebih sulit, itu saja. Tentu saja, kembali ketika saya mengambil kompiler, saya diberitahu bahwa pemindaian leksikal dapat mengambil lebih dari seperempat dari total waktu kompilasi.
David Thornley
4

Seperti yang diketahui beberapa orang, ada banyak muatan historis tentang format yang valid untuk nama variabel. Dan desainer bahasa selalu dipengaruhi oleh apa yang mereka ketahui saat mereka menciptakan bahasa baru.

Yang mengatakan, hampir sepanjang waktu bahasa tidak memungkinkan nama variabel untuk mulai dengan angka adalah karena itu adalah aturan desain bahasa. Seringkali karena aturan sederhana membuat parsing dan lexing bahasa menjadi jauh lebih mudah. Namun, tidak semua perancang bahasa tahu bahwa inilah alasan sebenarnya. Alat lexing modern membantu, karena jika Anda mencoba mendefinisikannya diizinkan, mereka akan memberi Anda konflik penguraian.

OTOH, jika bahasa Anda memiliki karakter yang dapat diidentifikasi secara unik untuk nama variabel pemberita, adalah mungkin untuk mengaturnya agar mereka mulai dengan angka. Variasi aturan serupa juga dapat digunakan untuk memungkinkan spasi dalam nama variabel. Tetapi bahasa yang dihasilkan cenderung tidak terlalu mirip dengan bahasa konvensional yang populer.

Untuk contoh bahasa templating HTML yang cukup sederhana yang memungkinkan variabel untuk memulai dengan angka dan memiliki ruang yang disematkan, lihat Qompose .

ahli statika
sumber
1
Sebenarnya, ada beberapa bahasa yang memungkinkan Anda memiliki karakter yang menandai pengidentifikasi. Mereka disebut "sigils" dan Anda memilikinya di Perl dan PHP.
Jason Baker
Kecuali Anda masih tidak diizinkan untuk memulai nama variabel dalam PHP dengan angka - aturan bahasa melarangnya. :-) Tapi Anda bisa di Qompose dengan alasan yang persis sama.
statika
4

Karena jika Anda mengizinkan kata kunci dan pengenal untuk memulai dengan karakter numerik, lexer (bagian dari kompiler) tidak dapat dengan mudah membedakan antara awal numerik literal dan kata kunci tanpa membuat jauh lebih rumit (dan lebih lambat).

Nicholas Carey
sumber
2
Proses lexing jarang menjadi hambatan. Tentu, itu membuat regex untuk token pengenal lebih kompleks, tetapi mereka masih bisa menjadi DFA super cepat. Runtime dari mereka adalah kacang dibandingkan dengan sebagian besar tugas yang harus diselesaikan oleh kompiler.
4

Pembatasannya sewenang-wenang. Berbagai Lisps mengizinkan nama simbol untuk memulai dengan angka.

Kyle Jones
sumber
4

COBOL memungkinkan variabel untuk memulai dengan angka.

brad
sumber
2

C ++ tidak dapat memilikinya karena desainer bahasa membuat aturan. Jika Anda ingin membuat bahasa Anda sendiri, Anda tentu bisa mengizinkannya, tetapi Anda mungkin akan mengalami masalah yang sama seperti yang mereka lakukan dan memutuskan untuk tidak mengizinkannya. Contoh nama variabel yang akan menyebabkan masalah:

0x, 2d, 5555

Kevin
sumber
Batasan ini berlaku dalam bahasa di mana sintaks semacam itu tidak diizinkan.
Jason Baker
2

Salah satu masalah utama tentang konvensi sintaksis yang santai adalah bahwa ia memperkenalkan disonansi kognitif ke dalam proses pengkodean. Bagaimana Anda berpikir tentang kode Anda bisa sangat dipengaruhi oleh kurangnya kejelasan yang akan diperkenalkan ini.

Bukankah Dykstra yang mengatakan bahwa "aspek terpenting dari alat apa pun adalah pengaruhnya terhadap penggunanya"?

mengalah
sumber
1

Mungkin karena memudahkan manusia untuk mengetahui apakah itu angka atau pengenal, dan karena tradisi. Memiliki pengidentifikasi yang dapat dimulai dengan digit tidak akan menyulitkan pemindaian leksikal sebanyak itu.

Tidak semua bahasa memiliki pengidentifikasi terlarang yang dimulai dengan angka. Di Forth, mereka bisa berupa angka, dan bilangan bulat kecil biasanya didefinisikan sebagai kata Forth (pengidentifikasi dasarnya), karena lebih cepat untuk membaca "2" sebagai rutinitas untuk mendorong 2 ke stack daripada mengenali "2" sebagai angka. yang nilainya 2. (Dalam memproses input dari programmer atau blok disk, sistem Forth akan membagi input sesuai dengan spasi. Akan mencoba untuk mencari token di kamus untuk melihat apakah itu kata yang didefinisikan, dan jika tidak akan berusaha menerjemahkannya menjadi angka, dan jika tidak akan menandai kesalahan.)

David Thornley
sumber
Masalahnya adalah Forth tidak benar-benar memiliki parser yang sangat canggih. Sungguh, yang perlu diperhatikan adalah jika pengidentifikasi berada di antara dua set spasi putih.
Jason Baker
1

Misalkan Anda mengizinkan nama simbol dimulai dengan angka. Sekarang anggaplah Anda ingin memberi nama variabel 12345foobar. Bagaimana Anda membedakan ini dari 12345? Ini sebenarnya tidak terlalu sulit untuk dilakukan dengan ekspresi reguler. Masalahnya sebenarnya adalah salah satu dari kinerja. Saya tidak bisa menjelaskan mengapa ini sangat rinci, tetapi pada dasarnya bermuara pada fakta bahwa membedakan 12345foobar dari 12345 membutuhkan pengulangan. Ini membuat ekspresi reguler menjadi non-deterministik.

Ada penjelasan yang jauh lebih baik tentang ini di sini .

Jason Baker
sumber
1
Bagaimana orang mendesain ekspresi reguler untuk memungkinkan variabel bernama ifqatau doubleztetapi tidak ifatau double? Masalah mendasar dengan memungkinkan pengidentifikasi untuk memulai dengan angka adalah bahwa ada bentuk hex hexal dan angka floating-point yang seluruhnya terdiri dari karakter alfanumerik (bahasa akan menggunakan sesuatu seperti $ 1234 atau h'1234 bukan 0x1234, dan memerlukan angka seperti 1E23 untuk memasukkan titik, dapat menghindari masalah itu). Perhatikan bahwa upaya untuk regex-parsing C sudah bisa tersandung oleh hal-hal seperti 0x12E+5.
supercat
1

mudah bagi kompilator untuk mengidentifikasi variabel menggunakan ASCII pada lokasi memori daripada angka.

Vivek
sumber
1

Kompiler memiliki 7 fase sebagai berikut:

  1. Analisis leksikal
  2. Analisis Sintaks
  3. Analisis Semantik
  4. Pembuatan Kode Menengah
  5. Optimasi Kode
  6. Pembuatan Kode
  7. Tabel Simbol

Mengulangi dihindari dalam fase analisis leksikal saat menyusun potongan kode. Variabel seperti Apple, kompiler akan segera tahu pengidentifikasi ketika bertemu dengan huruf 'A' pada fase Analisis leksikal. Namun, variabel seperti 123apple, kompiler tidak akan dapat memutuskan apakah itu angka atau pengidentifikasi sampai hits 'a' dan perlu mundur untuk masuk dalam fase analisis leksikal untuk mengidentifikasi bahwa itu adalah variabel. Tetapi tidak didukung di kompiler.

Saat Anda menguraikan token, Anda hanya perlu melihat karakter pertama untuk menentukan apakah itu pengenal atau literal dan kemudian mengirimnya ke fungsi yang benar untuk diproses. Jadi itu optimasi kinerja.

Harikesh
sumber
0

Saya pikir jawaban sederhana adalah bahwa hal itu bisa, batasannya adalah berdasarkan bahasa. Di C ++ dan banyak lainnya tidak bisa karena bahasa tidak mendukungnya. Itu tidak dibangun ke dalam aturan untuk memungkinkan itu.

Pertanyaannya adalah seperti menanyakan mengapa Raja tidak bisa memindahkan empat ruang sekaligus dalam Catur? Itu karena di Catur itu adalah langkah ilegal. Bisa di game lain pasti. Itu hanya tergantung pada aturan yang dimainkan.

kemiller2002
sumber
Kecuali bahwa C ++ baru-baru ini ditemukan oleh orang-orang yang masih hidup. Kita dapat bertanya kepada mereka mengapa mereka memilih hal-hal yang mereka lakukan, dan menolak alternatifnya. Hal yang sama tidak berlaku untuk catur.
Steve Jessop
Tapi bukan itu yang saya maksudkan. Ini analogi mengapa tidak ada angka di awal nama variabel, dan jawaban yang paling sederhana adalah, karena aturan bahasa tidak mengizinkannya.
kemiller2002
Tentu, tapi saya tidak berpikir si penanya itu bodoh. Dia mungkin sudah bekerja sejauh itu sendirian. Pertanyaan IMO adalah "mengapa aturan bahasa tidak mengizinkannya?". Dia ingin menjembatani kesenjangan antara mengetahui aturan dan memahaminya.
Steve Jessop
Ya, setelah merenungkan hal ini, saya menyadari ke mana Anda pergi. Anda benar juga. Saya kira saya sedikit menerapkan Occam's razor secara bebas dan berasumsi tidak ada jawaban nyata mengapa kecuali bahwa variabel tidak dimulai dengan angka, karena tidak ada angka.
kemiller2002
Saya tidak mengatakan Anda salah, ingatlah, kadang-kadang keputusan badan standar C ++ melebihi pemahaman fana, dan Anda berakhir dengan "karena mereka harus memutuskan sesuatu dan mereka memutuskan ini". Tapi setidaknya ada pertanyaan yang harus ditanyakan :-)
Steve Jessop
0

Awalnya itu hanya karena lebih mudah untuk mengingat (Anda dapat memberikan lebih banyak makna) nama variabel sebagai string daripada angka meskipun angka dapat dimasukkan dalam string untuk meningkatkan makna string atau memungkinkan penggunaan nama variabel yang sama tetapi memilikinya ditunjuk memiliki makna atau konteks yang terpisah, tapi dekat. Misalnya loop1, loop2 dll akan selalu memberi tahu Anda bahwa Anda berada dalam satu loop dan / atau loop 2 adalah loop dalam loop1. Mana yang Anda inginkan (memiliki makna lebih) sebagai variabel: alamat atau 1121298? Mana yang lebih mudah diingat? Namun, jika bahasa tersebut menggunakan sesuatu untuk menyatakan bahwa itu bukan hanya teks atau angka (seperti $ dalam $ address) itu benar-benar tidak boleh membuat perbedaan karena itu akan memberitahu kompiler bahwa apa yang berikut harus diperlakukan sebagai variabel ( pada kasus ini).

cjtech
sumber
0

Variabel dapat dianggap sebagai nilai juga selama waktu kompilasi oleh kompiler sehingga nilai dapat memanggil nilai lagi dan lagi secara rekursif

aravinth
sumber
0

Mengulangi dihindari dalam fase analisis leksikal saat menyusun potongan kode . Variabel seperti Apple; , kompiler akan segera mengetahui pengidentifikasi ketika memenuhi karakter huruf 'A' dalam fase Analisis leksikal. Namun, variabel seperti 123apple; , compiler tidak akan dapat memutuskan apakah angka atau pengenalnya sampai hits 'a' dan perlu mundur untuk masuk dalam fase analisis leksikal untuk mengidentifikasi bahwa itu adalah variabel. Tetapi tidak didukung di kompiler.

Referensi

Angelin Nadar
sumber
0

Tidak ada yang salah dengan itu ketika datang ke mendeklarasikan variabel.tapi ada beberapa ambiguitas ketika mencoba menggunakan variabel itu di tempat lain seperti ini:

biarkan 1 = "Halo dunia!" print (1) print (1)

cetak adalah metode umum yang menerima semua jenis variabel. jadi dalam situasi itu kompiler tidak tahu yang mana (1) pemrogram merujuk: 1 dari nilai integer atau 1 yang menyimpan nilai string. mungkin lebih baik bagi kompiler dalam situasi ini untuk memungkinkan untuk mendefinisikan sesuatu seperti itu tetapi ketika mencoba untuk menggunakan hal-hal yang ambigu ini, membawa kesalahan dengan kemampuan koreksi untuk bagaimana memperbaiki kesalahan itu dan menghapus ambiguitas ini.

Ali Torabi
sumber