Dlaczego nazwy funkcji numerycznych są niedozwolone?


10

Rozważ następujące:

$ 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

Zasadniczo, starałem się deklarować funkcje 1i 0co byłoby dla shorthands truea false, ale jak widać wpadłem na problem z użyciem nazwy numeryczne funkcje. To samo zachowanie występuje w przypadku aliasów i dwucyfrowych nazw.

Pytanie brzmi „dlaczego”? Czy jest to wymagane przez POSIX? czy po prostu dziwactwo muszli przypominających bourne?

Zobacz także powiązane pytanie z tym.


1
Rzeczy, które są wymagane przez posix, to w większości dziwactwa pocisków podobnych do Bourne'a. : P
mur

Widzę, co tu zrobiłeś . . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem Proszę odnieść się do meta.askubuntu.com/q/13807/295286 Powłoki / skrypty powłoki są i zawsze były na temat na Ask Ubuntu :) Jest to niezbędny temat do prawidłowego administrowania systemem każdego systemu Ubuntu
Sergiy Kolodyazhnyy

4
Warto zauważyć, że 0jest truew skryptach powłoki i 1jest false(tak naprawdę każdy niezerowy traktowany jest jako fałsz), na wypadek, gdyby ktoś czytający to nie był świadomy. Jest to odwrotnie niż w przypadku większości innych języków programowania.
Ethan Kamiński

2
@EthanKamiński tak, jeśli chodzi o statusy wyjścia poleceń , to absolutnie prawda. Zwracana wartość 0 jest truew powłoce. Jednak w interpretacji arytmetycznej $((...))odwracane są statusy powrotu - 1 oznacza, truea 0 oznacza falsespójność ze składnią języka C. Spróbuj na przykład bash -c 'echo $((1==1));echo $((1==2))' To, co próbowałem zrobić poza tym pytaniem, było w rzeczywistości „odwróceniem” zachowania. Zobacz ostatni przykład mojej odpowiedzi tutaj, aby zobaczyć, co dokładnie próbowałem zrobić. Głupi pomysł, ale mimo to działa
Sergiy Kolodyazhnyy

Odpowiedzi:


14

POSIX mówi:

2.9.5 Polecenie definicji funkcji

Funkcja jest nazwą zdefiniowaną przez użytkownika, która jest używana jako proste polecenie do wywołania polecenia złożonego z nowymi parametrami pozycyjnymi. Funkcja jest definiowana za pomocą „polecenia definicji funkcji”.

Format polecenia definicji funkcji jest następujący:

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

Funkcja nazywa się fname ; aplikacja powinna upewnić się, że jest to nazwa (patrz Nazwa XBD ) i że nie jest to nazwa specjalnego wbudowanego narzędzia. Implementacja może dopuszczać inne znaki w nazwie funkcji jako rozszerzenie. Implementacja powinna utrzymywać osobne przestrzenie nazw dla funkcji i zmiennych.

I:

3.235 Nazwa

W języku poleceń powłoki słowo składające się wyłącznie z podkreślników, cyfr i alfabetu z przenośnego zestawu znaków. Pierwszy znak imienia nie jest cyfrą.

Uwaga: Przenośny zestaw znaków jest szczegółowo zdefiniowany w Przenośnym zestawie znaków.

Zatem słowo zaczynające się od cyfry nie może być nazwą funkcji.


Nadal POSIX nie mówi dokładnie dlaczego, ale przyjmuję to jako odpowiedź „Ponieważ standardy”. Dzięki
Sergiy Kolodyazhnyy,

4
@SergiyKolodyazhnyy Powiedziałbym, że jest to dziedziczna rzecz. Ten standard nazw jest dość powszechny również w innych rzeczach (nazwy IIRC C również są zgodne z tym samym standardem), więc prawdopodobnie jest to kwestia uniksowa. Również w C ułatwia to parsowanie
mur

3
@muru w C przyniosłoby niejasności, gdyby było to dozwolone. Np. Co by to 1Lznaczyło? Nazwa funkcji? Czy long intdosłownie?
Ruslan

2
Dodając do powyższego, warto zauważyć, że w C nagie nazwy funkcji mogą działać jako wskaźnik do tej funkcji. Umożliwia to przekazywanie funkcji jako parametrów do funkcji, przechowywanie odwołań do nich w zmiennych itp. Często używane do wywołań zwrotnych. Jest to przeciwieństwo nazwy funkcji, po której następuje (), być może wraz z argumentami w środku, co oznacza wywołanie danej funkcji (i przyjmuje wartość zwracaną przez wywoływaną funkcję). Więc jeśli masz funkcję int f() { return 42; }w C, fjest poprawna w kontekście wskaźnika i f()jest poprawna w kontekście innym niż wskaźnik, liczba całkowita.
CVn

13

Jest to standard w wielu językach, aby zapobiec pomyłkom między operacjami matematycznymi a zmiennymi, funkcjami lub metodami.

Rozważać:

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

Jak widać, jeśli liczby byłyby dozwolone jako nazwy zmiennych lub funkcji, późniejsze wykonywanie matematyki w programie mogłoby stać się bardzo mylące i musiałbyś wymyślić twórcze obejścia, gdybyś musiał później zrobić matematykę z tymi liczbami. Może również powodować nieoczekiwane wyniki w niektórych językach. Wyobraź sobie, że zwiększasz liczbę dla pętli, ale jedna z cyfr jest już zmienną równą łańcuchowi. Natychmiast rzuciłby błąd. Jeśli nie jesteś oryginalnym autorem kodu, znalezienie błędu może zająć sporo czasu.

W skrócie, dlatego większość języków nie pozwala na użycie liczby jako nazwy zmiennej, funkcji, metody itp.


Zamierzałem skomentować: „ale zmienne w powłoce muszą zostać uzupełnione o $rozszerzenie”, ale z drugiej strony, jeśli powłoka jest inspirowana innymi językami, to chyba tak, a poza tym arytmetyczne ((zmienne rozszerzenia nie muszą mieć wiodącej pozycji $. OK, rozumiem to
Sergiy Kolodyazhnyy,

3
Tak, jest to konwencja, ponieważ przyniesie nieoczekiwane wyniki w prawie każdym języku, ale nawet w sytuacji, w której zadziała, może być bardzo trudny do zrozumienia dla każdego, kto będzie musiał pracować nad twoim kodem po tobie.
Josh

2
Rozbudowa arytmetyczna @SergiyKolodyazhnyy pozwala na odwoływanie się do nazw zmiennych bez $, więc jest to. Ale to prawdopodobnie drugorzędne w stosunku do innego powodu „po prostu przestrzegania wspólnej konwencji”
Hobbs

@obbs tak, absolutnie się z tym zgadzam
Sergiy Kolodyazhnyy

1
To wyjaśnienie „większości języków” nie ma sensu dla powłok. Wszystkie pociski w stylu Bourne'a mają parametry, których nazwy wyglądać literałów liczbowych lub operatorów: 0nazwy powłoki lub skryptu 1, 2, ..., dla parametrów pozycyjnych, *dla nich dołączył, -do włączonych opcji, ?za ostatni stan wyjścia, a !dla najnowszy PID zadania asynchronicznego. (Tak więc, nawet w $(( ))The $często jest potrzebne.) Kod pokazany tutaj wykazać sugerowanego uzasadnienie nie jest skryptem powłoki Bourne'a dla każdego stylu, ponieważ nie ma sposobu, aby wykazać to w ten sposób, jak to nie ma zastosowania do im.
Eliah Kagan,

10

W C rozważmy wyrażenie takie jak:

1000l + 2.0f;

Czy 1000lzmienna czy stała? Ponieważ nazwy zmiennych nie mogą zaczynać się cyfrą, musi być stała. To sprawia, że ​​parsowanie jest łatwiejsze i bardziej rygorystyczne (literówki 1000kmożna łatwo złapać). Łatwiej jest też mieć jedną regułę dla zmiennych i nazw funkcji, ponieważ funkcje można również traktować jak zmienne. Teraz, oczywiście, parsery są znacznie bardziej złożone i wydajne, a my mamy takie rzeczy jak niestandardowe literały w C ++. Ale w dawnych czasach prehistorii poświęcenie odrobiny niepotrzebnej elastyczności może znacznie skrócić czas kompilacji (lub interpretacji) (a ludzie nadal narzekają na czasy kompilacji w C ++).

I możesz zobaczyć efekty wpływu C w całym języku powłoki, więc nie jest zaskakujące, że powłoka Bourne'a (lub powłoka C), a zatem POSIX, ograniczyła klasę dozwolonych nazw do tego samego co klasa C.


2
Jak wyjaśniają , jest to poprawne. Nie chodzi o to, że te same rozważania dotyczą wszystkich języków ani o to, że powłoki w stylu Bourne'a mają składnię podobną do C, ale że kultura związana z C była silna i projektanci powłok musieli wymyślić pewne gwarancje co do identyfikatorów dozwolony. Myślę, że można by użyć przykładów „można zobaczyć efekty wpływu C w całym języku powłoki”, ponieważ podobieństwa między nimi naprawdę nie przeważają nad różnicami (na przykład, jakie liczby są uważane za prawdziwe ). Niemniej jednak ta odpowiedź jest poprawna.
Eliah Kagan,

@Eliah prawdopodobnie liczby są również bezpośrednią konsekwencją statusu wyjścia dla sukcesu i porażki w C, więc mam tendencję do myślenia w kategoriach sukcesu i porażki zamiast prawdy i fałszu podczas pisania testów powłoki. Masz rację, że mnóstwo składni powłoki nie przypomina C, ale przykłady obejmują nawiasy klamrowe, średniki, zwarcie &&i ||brak wsparcia dla ASCII nul w ciągach,
Olorin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.