Perché i nomi delle funzioni numeriche non sono ammessi?


10

Considera quanto segue:

$ 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

Fondamentalmente, stavo cercando di dichiarare le funzioni 1e 0quali sarebbero le scorciatoie per truee false, ma come puoi vedere ho riscontrato problemi con l'uso di nomi numerici nelle funzioni. Lo stesso comportamento si verifica con alias e nomi a due cifre.

La domanda è "perché"? È obbligatorio per POSIX? o solo una stranezza di conchiglie simili a bourne?

Vedi anche la domanda correlata a questo.


1
Le cose che sono richieste da posix sono per lo più stranezze di conchiglie tipo Bourne. : P
muru,

Vedo quello che hai fatto là . . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem Fare riferimento a meta.askubuntu.com/q/13807/295286 Gli script di shell / shell sono e sono sempre stati in argomento su Ask Ubuntu :) È un argomento essenziale per la corretta amministrazione di sistema di qualsiasi sistema Ubuntu
Sergiy Kolodyazhnyy

4
Vale la pena notare che 0è truein shell scripting ed 1è false(in realtà, qualsiasi diverso da zero viene trattato come falso), nel caso in cui chiunque legga questo non sia a conoscenza. Ciò è arretrato rispetto alla maggior parte degli altri linguaggi di programmazione.
Ethan Kaminski,

2
@EthanKaminski sì, per quanto riguarda gli stati di uscita dei comandi , è assolutamente vero. Il valore di ritorno di 0 è truenella shell. Tuttavia, nell'espansione aritmetica gli $((...))stati di ritorno sono invertiti - 1 è truee 0 è falseper coerenza con la sintassi del linguaggio C. Prova ad esempio bash -c 'echo $((1==1));echo $((1==2))' Quello che stavo cercando di fare al di fuori di questa domanda era in realtà "invertire" il comportamento. Vedi l'ultimo esempio sulla mia risposta qui per vedere cosa stavo esattamente cercando di fare. Idea sciocca, ma funziona comunque
Sergiy Kolodyazhnyy il

Risposte:


14

POSIX dice:

2.9.5 Comando di definizione della funzione

Una funzione è un nome definito dall'utente che viene utilizzato come semplice comando per chiamare un comando composto con nuovi parametri posizionali. Una funzione viene definita con un "comando di definizione della funzione".

Il formato di un comando di definizione della funzione è il seguente:

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

La funzione si chiama fname ; l'applicazione deve garantire che sia un nome (vedere Nome XBD ) e che non sia il nome di un'utilità integrata speciale. Un'implementazione può consentire altri caratteri in un nome di funzione come estensione. L'implementazione deve mantenere spazi dei nomi separati per funzioni e variabili.

E:

3.235 Nome

Nel linguaggio dei comandi della shell, una parola composta esclusivamente da caratteri di sottolineatura, cifre e alfabeti dal set di caratteri portatile. Il primo carattere di un nome non è una cifra.

Nota: il set di caratteri portatile è definito in dettaglio nel set di caratteri portatile.

Quindi una parola che inizia con una cifra non può essere un nome di funzione.


Tuttavia POSIX non dice bene perché, ma lo prenderò come risposta "Perché gli standard". Grazie
Sergiy Kolodyazhnyy il

4
@SergiyKolodyazhnyy Direi che è una cosa ereditata. Questo standard per i nomi è abbastanza comune anche in altre cose (anche i nomi IIRC C seguono lo stesso standard), quindi probabilmente è una cosa Unix. Inoltre, in C, rende più semplice l'analisi
muru

3
@muru in C porterebbe qualche ambiguità se fosse permesso. Ad esempio cosa 1Lsignificherebbe? Un nome di funzione? O un long intletterale?
Ruslan,

2
Aggiungendo a quanto sopra, vale la pena notare che in C, un nome di funzione nudo può fungere da puntatore a quella funzione. Ciò consente di passare funzioni come parametri a una funzione, memorizzare riferimenti ad esse in variabili, ecc. Spesso utilizzate per i callback. Questo in contrasto con il nome della funzione seguito da (), possibilmente con argomenti all'interno, che indica una chiamata alla funzione in questione (e assume il valore che viene restituito dalla funzione chiamata). Pertanto, se si dispone di una funzione int f() { return 42; }in C, fè valida in un contesto di puntatore ed f()è valida in un contesto intero senza puntatore.
un CVn

13

Questo è uno standard in molte lingue per prevenire la confusione tra operazioni matematiche e variabili o funzioni o metodi.

Ritenere:

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

Come puoi vedere, se i numeri fossero ammessi come nomi di variabili o di funzioni, fare matematica in un secondo momento in un programma potrebbe diventare molto confuso e dovresti trovare soluzioni creative se avessi bisogno di fare matematica con quei numeri in seguito. Può anche produrre risultati imprevisti in alcune lingue. Immagina di aumentare un numero per un ciclo, ma una delle cifre è già una variabile uguale a una stringa. Sarebbe immediatamente un errore. Se non fossi l'autore originale del codice, questo errore potrebbe richiedere del tempo per essere trovato.

In breve, questo è il motivo per cui la maggior parte delle lingue non consente di utilizzare un numero come nome di una variabile o funzione o metodo o ecc.


Stavo per commentare "ma le variabili nella shell devono essere anteposte $per essere espanse", ma poi di nuovo se la shell è ispirata da altre lingue, va bene, suppongo, inoltre nelle ((variabili di espansione aritmetica non è richiesto di avere il comando $. OK, posso capirlo
Sergiy Kolodyazhnyy,

3
Sì, è una convenzione perché creerà risultati imprevisti in quasi tutte le lingue, ma, anche in una situazione in cui funzionerebbe, può rendere il codice molto difficile da comprendere per chiunque debba lavorare sul codice dopo di te.
Josh

2
L'espansione aritmetica di @SergiyKolodyazhnyy consente di fare riferimento a nomi di variabili senza $, quindi esiste. Ma questo è probabilmente secondario all'altra ragione del "solo seguire una convenzione comune"
hobbs il

@hobbs sì, assolutamente d'accordo con questo
Sergiy Kolodyazhnyy,

1
Questa spiegazione "la maggior parte delle lingue" ha poco senso per le conchiglie. Tutte le shell stile Bourne hanno parametri i cui nomi assomigliare letterali o operatori numerici: 0per il nome della shell o dello script, 1, 2, ..., per i parametri posizionali, *per loro uniti, -per le opzioni attivate, ?per l'ultimo stato di uscita, e !per la il PID del lavoro asincrono più recente. (Quindi, anche in $(( )), $è spesso necessario.) Il codice mostrato qui per dimostrare la logica suggerita non è uno script per qualsiasi shell in stile Bourne, poiché non c'è modo di dimostrarlo in questo modo, poiché non si applica a loro.
Eliah Kagan,

10

In C, considera un'espressione come:

1000l + 2.0f;

È 1000luna variabile o una costante? Poiché i nomi delle variabili non possono iniziare con una cifra, deve essere una costante. Ciò rende l'analisi più semplice e più rigorosa (errori di battitura come 1000kpossono essere facilmente individuati). È anche più semplice avere un'unica regola per variabili e nomi di funzioni, poiché anche le funzioni possono essere trattate come variabili. Ora , naturalmente, i parser sono molto più complessi e potenti e abbiamo cose come letterali personalizzati in C ++. Ma in quei tempi antichi della preistoria, sacrificare un po 'di flessibilità non necessaria potrebbe rendere i tempi di compilazione (o interpretazione) molto più brevi (e le persone si lamentano ancora dei tempi di compilazione C ++).

E puoi vedere gli effetti di un'influenza C in tutto il linguaggio della shell, quindi non sorprende che la shell Bourne (o shell C) e, quindi, POSIX, abbia limitato la classe dei nomi consentiti allo stesso di quella di C.


2
Come vanno le spiegazioni , questa è quella corretta. E ' non è che le stesse considerazioni valgono per tutte le lingue o che le coperture in stile Bourne avere una sintassi simile a quella di C, ma che la cultura associata a C era forte e shell progettisti hanno dovuto venire con alcune garanzie su ciò che sarebbe identificatori permesso. Penso che questo potrebbe usare esempi di "puoi vedere gli effetti di un'influenza C in tutto il linguaggio shell", poiché le somiglianze tra loro in realtà non superano le differenze (pensa a quali numeri sono considerati veri , per esempio). Tuttavia, questa risposta è corretta.
Eliah Kagan,

@Eliah probabilmente la cosa dei numeri è anche una conseguenza diretta degli stati di uscita per successo e fallimento in C, quindi tendo a pensare in termini di successo e fallimento invece di vero e falso quando si scrivono test di shell. Hai ragione in un sacco di sintassi della shell che non assomiglia a C, ma gli esempi includono parentesi graffe, punti e virgola, cortocircuito &&e ||mancanza di supporto per il nul ASCII nelle stringhe,
Olorin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.