Mengapa nama fungsi numerik tidak diizinkan?

10

Pertimbangkan yang berikut ini:

$ ksh -c '1(){ echo hi;};1'
ksh: 1: invalid function name
$ dash -c '1(){ echo hi;};1'
dash: 1: Syntax error: Bad function name
$ bash -c '1(){ echo hi;};1'
bash: `1': not a valid identifier
bash: 1: command not found
$ mksh -c '1(){ echo hi;};1'
hi

Pada dasarnya, saya mencoba untuk mendeklarasikan fungsi 1dan 0yang akan menjadi singkatan untuk truedan false, tetapi seperti yang Anda lihat saya mengalami masalah dengan menggunakan nama numerik dalam fungsi. Perilaku yang sama terjadi dengan alias dan nama dua digit.

Pertanyaannya adalah "mengapa"? Apakah itu diamanatkan oleh POSIX? atau hanya kekhasan cangkang mirip bourne?

Lihat juga pertanyaan terkait dengan yang ini.

Sergiy Kolodyazhnyy
sumber
1
Hal-hal yang dimandatkan oleh posix sebagian besar kadang-kadang kebiasaan quirks seperti Bourne. : P
muru
Saya melihat apa yang Anda lakukan di sana . . . > :) lol
Sergiy Kolodyazhnyy
4
@fkraiem Silakan merujuk ke meta.askubuntu.com/q/13807/295286 Script shell / shell adalah dan selalu pada topik di Tanya Ubuntu :) Ini adalah topik penting untuk administrasi sistem yang tepat dari setiap sistem Ubuntu
Sergiy Kolodyazhnyy
4
Itu perlu dicatat bahwa 0adalah truedi scripting shell dan 1adalah false(benar-benar, setiap non-nol diperlakukan sebagai palsu), dalam kasus orang membaca ini tidak menyadari. Ini mundur dari sebagian besar bahasa pemrograman lainnya.
Ethan Kaminski
2
@EthanKaminski ya, sejauh status keluar dari perintah , itu benar sekali. Nilai balik 0 truedalam shell. Namun, dalam ekspansi aritmatika, $((...))status pengembalian dibalik - 1 adalah truedan 0 falseuntuk konsistensi dengan sintaks C-language. Coba misalnya bash -c 'echo $((1==1));echo $((1==2))' Apa yang saya coba lakukan di luar pertanyaan ini sebenarnya "membalikkan" perilaku. Lihat contoh terakhir pada jawaban saya di sini untuk melihat apa sebenarnya yang saya coba lakukan. Gagasan konyol, tapi tetap berhasil
Sergiy Kolodyazhnyy

Jawaban:

14

POSIX mengatakan:

2.9.5 Perintah Definisi Fungsi

Fungsi adalah nama yang ditentukan pengguna yang digunakan sebagai perintah sederhana untuk memanggil perintah majemuk dengan parameter posisi baru. Suatu fungsi didefinisikan dengan "perintah definisi fungsi".

Format perintah definisi fungsi adalah sebagai berikut:

 fname ( ) compound-command [io-redirect ...]

Fungsi ini bernama fname ; aplikasi harus memastikan bahwa itu adalah nama (lihat Nama XBD ) dan itu bukan nama utilitas bawaan khusus. Implementasi dapat memungkinkan karakter lain dalam nama fungsi sebagai ekstensi. Implementasi harus memelihara ruang nama yang terpisah untuk fungsi dan variabel.

Dan:

3.235 Nama

Dalam bahasa perintah shell, kata yang hanya terdiri dari garis bawah, digit, dan alfabet dari set karakter portabel. Karakter pertama dari sebuah nama bukan digit.

Catatan: Perangkat Karakter Portable didefinisikan secara rinci dalam Perangkat Karakter Portable.

Jadi kata yang dimulai dengan digit tidak boleh berupa nama fungsi.

muru
sumber
Masih POSIX tidak cukup mengatakan mengapa, tapi saya akan menganggapnya sebagai "Karena standar" jawaban. Terima kasih
Sergiy Kolodyazhnyy
4
@SergiyKolodyazhnyy Saya akan mengatakan itu adalah hal yang diwariskan. Standar untuk nama-nama ini cukup umum dalam hal-hal lain juga (nama IIRC C juga mengikuti standar yang sama), jadi mungkin itu adalah sesuatu yang Unix. Juga, dalam C, membuatnya lebih mudah untuk mengurai
muru
3
@uru di C itu akan membawa beberapa ambiguitas jika diizinkan. Misalnya apa 1Lartinya? Nama fungsi? Atau long intliteral?
Ruslan
2
Menambahkan ke atas, perlu dicatat bahwa dalam C, nama fungsi kosong dapat bertindak sebagai penunjuk ke fungsi itu. Ini memungkinkan Anda untuk melewatkan fungsi sebagai parameter ke fungsi, menyimpan referensi ke mereka dalam variabel, dll. Sering digunakan untuk panggilan balik. Ini berbeda dengan nama fungsi yang diikuti oleh (), mungkin dengan argumen di dalamnya, yang menunjukkan panggilan ke fungsi yang bersangkutan (dan mengambil nilai yang dikembalikan oleh fungsi yang dipanggil). Jadi jika Anda memiliki fungsi int f() { return 42; }dalam C, fvalid dalam konteks pointer, dan f()valid dalam konteks integer non-pointer.
CVn
13

Itu adalah standar dalam banyak bahasa untuk mencegah kebingungan antara operasi matematika dan variabel atau fungsi atau metode.

Mempertimbangkan:

var 1 = 100

print 1*10 //should return 10 but would instead return 1000

var x = 5
x += 1
print x //returns 105, not 6    

def 100(num)
  return num * 1000
end

var y = 10 + 100(10)
print y // returns 100010 instead of 1010

Seperti yang Anda lihat, jika angka dibolehkan sebagai nama variabel atau fungsi, mengerjakan matematika di kemudian hari dalam program mungkin akan sangat membingungkan dan Anda harus membuat solusi kreatif jika Anda perlu benar-benar melakukan matematika dengan angka-angka itu nanti. Itu juga dapat menghasilkan hasil yang tidak terduga dalam beberapa bahasa. Bayangkan Anda menambah angka untuk satu lingkaran tetapi salah satu digit sudah menjadi variabel yang menyamai string. Itu akan segera melempar kesalahan. Jika Anda bukan pembuat kode asli, kesalahan itu bisa memakan waktu cukup lama untuk ditemukan.

Singkatnya, inilah mengapa sebagian besar bahasa tidak memungkinkan Anda untuk menggunakan angka sebagai nama variabel atau fungsi atau metode atau lainnya.

Josh
sumber
Saya akan berkomentar "tetapi variabel dalam shell perlu ditambahkan terlebih dahulu $untuk diperluas" tetapi sekali lagi jika shell terinspirasi oleh bahasa lain, tidak apa-apa saya kira, ditambah dalam ((variabel ekspansi aritmatika, variabel tidak diharuskan untuk memimpin $. OK, saya bisa mengerti itu
Sergiy Kolodyazhnyy
3
Ya, itu adalah konvensi karena akan menghasilkan hasil yang tidak terduga di hampir setiap bahasa, tetapi, bahkan dalam situasi di mana ia akan bekerja, itu dapat membuat kode sangat sulit untuk dipahami oleh siapa saja yang harus mengerjakan kode Anda setelah Anda.
Josh
2
Ekspansi aritmatika @SergiyKolodyazhnyy memungkinkan referensi nama variabel tanpa $, jadi begitulah. Tapi itu mungkin sekunder untuk alasan lain "hanya mengikuti konvensi umum"
hobbs
@ hobbs ya, sangat setuju dengan itu
Sergiy Kolodyazhnyy
1
Penjelasan "sebagian besar bahasa" ini tidak masuk akal untuk shell. Semua kerang Bourne-gaya memiliki parameter yang namanya terlihat seperti literal numerik atau operator: 0untuk shell atau script nama, 1, 2, ..., untuk parameter posisi, *bagi mereka bergabung, -untuk pilihan diaktifkan, ?untuk status keluar terakhir, dan !untuk PID pekerjaan asinkron terbaru. (Jadi, bahkan dalam $(( )), $sering diperlukan.) Kode yang ditunjukkan di sini untuk menunjukkan alasan yang disarankan bukanlah skrip untuk shell gaya Bourne, karena tidak ada cara untuk menunjukkannya seperti itu, karena tidak berlaku untuk mereka.
Eliah Kagan
10

Dalam C, pertimbangkan ungkapan seperti:

1000l + 2.0f;

Apakah 1000lvariabel atau konstanta? Karena nama variabel tidak dapat dimulai dengan angka, itu harus berupa konstanta. Ini membuat penguraian lebih mudah dan lebih ketat (kesalahan ketik seperti 1000kdapat dengan mudah ditangkap). Lebih mudah memiliki aturan tunggal untuk variabel dan nama fungsi, karena fungsi juga dapat diperlakukan sebagai variabel. Sekarang tentu saja, parser jauh lebih kompleks dan kuat, dan kami memiliki hal-hal seperti literal khusus di C ++. Namun di masa prasejarah kuno, mengorbankan sedikit fleksibilitas yang tidak perlu bisa membuat kompilasi Anda (atau interpretasi) kali lebih singkat (dan orang-orang masih mengeluh tentang waktu kompilasi C ++).

Dan Anda dapat melihat efek dari pengaruh C di seluruh bahasa shell, jadi tidak mengherankan bahwa shell Bourne (atau C shell) dan karenanya, POSIX, telah membatasi kelas nama yang diizinkan untuk sama dengan yang dari C.

Olorin
sumber
2
Sebagai penjelasan , ini adalah yang benar. Ini bukan bahwa pertimbangan yang sama berlaku untuk semua bahasa atau bahwa kerang Bourne-gaya memiliki sintaks mirip dengan C, tetapi bahwa budaya terkait dengan C adalah kuat dan desainer shell harus datang dengan beberapa jaminan seperti apa pengidentifikasi akan diizinkan. Saya pikir ini bisa menggunakan contoh "Anda dapat melihat efek dari pengaruh C di seluruh bahasa shell," karena kesamaan di antara mereka benar - benar tidak melebihi perbedaan (pikirkan tentang angka apa yang dianggap benar , misalnya). Meskipun demikian, jawaban ini benar.
Eliah Kagan
@ Eliah bisa dibilang nomor hal juga merupakan konsekuensi langsung dari status keluar untuk sukses dan gagal di C, jadi saya cenderung berpikir dalam hal keberhasilan dan kegagalan, bukan benar dan salah ketika menulis tes shell. Anda benar bahwa banyak sintaks shell tidak seperti C, tetapi contohnya termasuk kawat gigi, titik koma, hubungan arus pendek &&dan ||, kurangnya dukungan untuk string ASCII nul dalam string,
Olorin