Sayısal işlev adlarına neden izin verilmiyor?


10

Aşağıdakileri göz önünde bulundur:

$ 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

Temelde, işlevlerini bildirmek için çalışıyordu 1ve 0bunun için kestirme olur trueve false, ama gördüğünüz gibi ben fonksiyonlarda sayısal isimler kullanarak sorunla karşılaştık. Aynı davranış takma adlarda ve iki basamaklı adlarda da görülür.

Soru "neden"? POSIX tarafından zorunlu kılındı ​​mı? ya da sadece bir bourne benzeri mermi mi?

Bununla ilgili soruya da bakınız .


1
Posix tarafından zorunlu kılınan şeyler çoğunlukla Bourne benzeri mermilerin tuhaflıklarıdır. : P
muru

Orada ne yaptığınızı görüyorum. . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem bakınız meta.askubuntu.com/q/13807/295286 / kabuk komut ve her zaman Ubuntu Ask :) Herhangi Ubuntu sisteminin düzgün sistem yönetiminin için önemli bir konu üzerinde konu üzerine olmuştur Kabuklar
Sergiy Kolodyazhnyy

4
Belirterek It yetmeyecek 0olan truekabuk komut dosyası ve 1bir falsebu habersiz okuma durumda herkes, (gerçekten, herhangi olmayan sıfır yanlış olarak kabul edilir). Bu, diğer programlama dillerinin çoğundan geriye dönüktür.
Ethan Kaminski

2
@ThanKaminski evet, komutların çıkış durumlarına gelince , bu kesinlikle doğrudur. 0'ın dönüş değeri truekabuktadır. Ancak, aritmetik genişleme $((...))dönüş durumları ters çevrilir - 1 trueve 0, falseC dili sözdizimi ile tutarlılık içindir. Örneğin bash -c 'echo $((1==1));echo $((1==2))' bu sorunun dışında yapmaya çalıştığım şey aslında davranışı "tersine çevirdi". Cevabım son örneğe bakın burada tam olarak yapmaya çalıştığım ne olduğunu görmek için. Aptalca bir fikir, ama yine de çalışıyor
Sergiy Kolodyazhnyy

Yanıtlar:


14

POSIX diyor ki:

2.9.5 İşlev Tanım Komutu

İşlev, yeni konum parametreleriyle bir bileşik komutu çağırmak için basit bir komut olarak kullanılan kullanıcı tanımlı bir addır. Bir işlev, "işlev tanımlama komutu" ile tanımlanır.

İşlev tanımı komutunun biçimi aşağıdaki gibidir:

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

Bu işleve fname adı verilir ; Uygulama bir isim (XBd bkz olmasını sağlayacaktır Adı ) ve yerleşik yarar desteğiyle, özel adıdır olmadığını. Bir uygulama, işlev adındaki diğer karakterlerin uzantı olarak kullanılmasına izin verebilir. Uygulama, işlevler ve değişkenler için ayrı ad boşlukları bulundurmalıdır.

Ve:

3.235 İsim

Kabuk komut dilinde, taşınabilir karakter kümesinden yalnızca alt çizgi, rakam ve alfabetik sözcüklerden oluşan bir sözcük. Bir adın ilk karakteri bir rakam değildir.

Not: Taşınabilir Karakter Kümesi, Taşınabilir Karakter Kümesinde ayrıntılı olarak tanımlanmıştır.

Dolayısıyla, rakamla başlayan bir kelime işlev adı olamaz.


Hala POSIX nedenini tam olarak söylemiyor, ama bunu "Çünkü standartlar" cevabı olarak alacağım. Teşekkürler
Sergiy Kolodyazhnyy

4
@SergiyKolodyazhnyy Kalıtımsal bir şey olduğunu söyleyebilirim. İsimler için bu standart diğer şeylerde de oldukça yaygındır (IIRC C isimleri de aynı standardı takip eder), bu yüzden muhtemelen bir Unix şeydir. Ayrıca, C, ayrıştırmak kolaylaştırır
muru

3
C de muru izin verilirse bazı belirsizlikler getirirdi. Örneğin ne 1Lanlama geliyor? İşlev adı? Yoksa long intgerçek mi?
Ruslan

2
Yukarıdakilere ek olarak, C'de çıplak bir işlev adının bu işleve bir işaretçi olarak davranabileceğini belirtmek gerekir. Bu, işlevleri bir işleve parametre olarak iletmenize, bunlara başvuruları değişkenlerde depolamanıza vb. Olanak sağlar. Genellikle geri aramalar için kullanılır. Bu, işlevin adından farklı olarak (), muhtemelen içindeki bağımsız değişkenlerle, söz konusu işleve çağrı anlamına gelir (ve çağrılan işlevin döndürdüğü değeri alır). Bu nedenle int f() { return 42; }, C'de bir işleviniz varsa , fişaretçi bağlamında f()geçerlidir ve işaretçi olmayan, tamsayı bağlamında geçerlidir.
CVn

13

Bu, matematiksel işlemler ile değişkenler veya işlevler veya yöntemler arasındaki karışıklığı önlemek için birçok dilde bir standarttır.

Düşünmek:

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

Gördüğünüz gibi, sayılara değişken veya işlev adı olarak izin verildiyse, daha sonra bir programda matematik yapmak çok kafa karıştırıcı olabilir ve daha sonra bu sayılarla gerçekten matematik yapmanız gerekirse yaratıcı çözümler bulmanız gerekir. Ayrıca bazı dillerde beklenmedik sonuçlar üretebilir. Bir döngü için bir sayı artırdığınızı, ancak rakamlardan birinin zaten bir dizeye eşit olan bir değişken olduğunu düşünün. Hemen bir hata verir. Kodun orijinal yazarı siz değilseniz, bu hatanın bulunması biraz zaman alabilir.

Özetle, bu yüzden çoğu dil bir sayıyı bir değişkenin veya fonksiyonun veya yöntemin vb. Adı olarak kullanmanıza izin vermez.


"Kabuktaki değişkenlerin $genişletilmesi için önceden eklenmesi gerekiyor" yorumunu yapıyordum, ancak daha sonra kabuk diğer dillerden esinlenirse, sorun yok sanırım, artı aritmetik genişleme ((değişkenlerinde öncü olması gerekmez $. Tamam, anlayabiliyorum
Sergiy Kolodyazhnyy

3
Evet, bu bir sözleşmedir, çünkü hemen hemen her dilde beklenmedik sonuçlar yaratacaktır, ancak çalışacağı bir durumda bile, kodunuz üzerinde çalışmanız gereken herkes için kodun anlaşılmasını çok zorlaştırabilir.
Josh

2
@SergiyKolodyazhnyy aritmetik genişletme değişken adlarına olmadan başvurmayı sağlar $, bu yüzden var. Ama bu muhtemelen "sadece ortak konvansiyonu izleyen" diğer nedene ikincil
ocaklar

@hobbs evet, kesinlikle katılıyorum
Sergiy Kolodyazhnyy

1
Bu "çoğu dil" açıklaması kabuklar için pek bir anlam ifade etmiyor. Tüm Bourne tarzı kabukları isimleri parametreleri var gibi bakmak sayısal değişmezleri veya operatörler: 0kabuk veya komut dosyası adı için, 1, 2, ..., konumsal parametreler için, *onları katıldı için, -etkin seçenekler için, ?son çıkış durumu ve !için en yeni eşzamansız işin PID'si. (Böylece, hatta $(( )), $çoğu zaman gereklidir.) Önerilen gerekçesini göstermek için burada gösterilen kodu herhangi Bourne tarzı kabuğu için bir senaryo değil, bu şekilde göstermek için bir yolu yoktur, çünkü olarak bu geçerli değildir etmek onlar.
Eliah Kagan

10

C'de, şöyle bir ifadeyi düşünün:

1000l + 2.0f;

1000ldeğişken veya sabit? Değişken adları bir rakamla başlayamadığından, sabit olması gerekir. Bu ayrışmayı kolaylaştırır ve daha sıkı hale getirir (örneğin yazım hataları 1000kkolayca yakalanabilir). İşlevler de değişken olarak kabul edilebildiğinden, değişkenler ve işlev adları için tek bir kurala sahip olmak daha kolaydır. Şimdi tabii ki, ayrıştırıcılar çok daha karmaşık ve güçlü, ve biz C ++ özel değişmezleri gibi şeyler var. Ancak, tarih öncesi o eski günlerde, biraz gereksiz esneklikten ödün vermek derleme (veya yorumlama) sürelerinizi daha kısa hale getirebilir (ve insanlar hala C ++ derleme sürelerinden şikayet edebilirler).

Ve kabuk etkisi boyunca bir C etkisinin etkilerini görebilirsiniz, bu nedenle Bourne kabuğunun (veya C kabuğunun) ve dolayısıyla POSIX'in izin verilen ad sınıfını C ile aynı sınırlandırması şaşırtıcı değildir.


2
Gibi açıklamalar gidin bu doğru olandır. O var değil aynı hususlar C benzer bir sözdizimi var Bourne tarzı kabukları tüm dillere veya geçerli, ama bu C ile ilişkili kültür güçlüydü ve kabuk tasarımcıları ile gelip vardı bazı tanımlayıcılar olurdu ne olduğuna teminat izin verdi. Gerçekten aralarındaki benzerlikler gibi "sen kabuk dili boyunca C etki etkilerini görebilirsiniz" Bunun örneklerini kullanabilirsiniz düşünüyorum yok (sayılar olarak kabul edilir düşün farklılıklar ağır bastığı gerçek örneğin). Bununla birlikte, bu cevap doğrudur.
Eliah Kagan

@Eliah muhtemelen sayı şey de C başarı ve başarısızlık için çıkış durumlarının doğrudan bir sonucudur, bu yüzden kabuk testleri yazarken doğru ve yanlış yerine başarı ve başarısızlık açısından düşünme eğilimindedir. Çok sayıda kabuk sözdiziminin C gibi bir şey olmadığı konusunda haklısınız, ancak örnekler arasında parantezler, noktalı virgüller, kısa devre &&ve ||dizelerde ASCII
nulü
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.