Warum sind numerische Funktionsnamen nicht erlaubt?

10

Folgendes berücksichtigen:

$ 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

Im Grunde war ich versuche , Funktionen zu erklären 1und 0welche wären Kürzel für trueund false, aber wie man sehen kann ich lief in Probleme mit numerischen Namen in Funktionen. Das gleiche Verhalten tritt bei Aliasnamen und zweistelligen Namen auf.

Frage ist "warum"? Wird es von POSIX beauftragt? oder nur eine Eigenart von Bourne-ähnlichen Muscheln?

Siehe auch verwandte Fragen zu dieser.

Sergiy Kolodyazhnyy
quelle
1
Dinge, die von posix vorgegeben werden, sind meistens Macken von Bourne-ähnlichen Muscheln. : P
Muru
Ich sehe, was du dort getan hast. . . > :) lol
Sergiy Kolodyazhnyy
4
@fkraiem Bitte beziehen Sie sich auf meta.askubuntu.com/q/13807/295286 Shells / Shell-Scripting sind und waren immer ein Thema bei Ask Ubuntu :) Es ist ein wesentliches Thema für die ordnungsgemäße Systemadministration eines Ubuntu-Systems
Sergiy Kolodyazhnyy
4
Es ist erwähnenswert, dass 0es sich trueum Shell-Scripting handelt und dies 1ist false(tatsächlich wird jede Nicht-Null als falsch behandelt), falls jemand, der dies liest, es nicht weiß. Dies ist rückwärts von den meisten anderen Programmiersprachen.
Ethan Kaminski
2
@EthanKaminski yep, was den Exit-Status von Befehlen betrifft, ist das absolut wahr. Der Rückgabewert 0 ist truein der Shell. Bei der arithmetischen Erweiterung werden die $((...))Rückgabestatus jedoch umgedreht - 1 ist trueund 0 steht falsefür Konsistenz mit der C-Sprachsyntax. Versuchen Sie zum Beispiel, bash -c 'echo $((1==1));echo $((1==2))' was ich außerhalb dieser Frage zu tun versuchte, war tatsächlich das Verhalten "umzukehren". Sehen Sie sich das letzte Beispiel meiner Antwort hier an, um zu sehen, was genau ich versucht habe. Dumme Idee, aber funktioniert trotzdem
Sergiy Kolodyazhnyy

Antworten:

14

POSIX sagt:

2.9.5 Funktionsdefinitionsbefehl

Eine Funktion ist ein benutzerdefinierter Name, der als einfacher Befehl zum Aufrufen eines zusammengesetzten Befehls mit neuen Positionsparametern verwendet wird. Eine Funktion wird mit einem "Funktionsdefinitionsbefehl" definiert.

Das Format eines Funktionsdefinitionsbefehls lautet wie folgt:

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

Die Funktion heißt fname ; Die Anwendung muss sicherstellen, dass es sich um einen Namen handelt (siehe XBD- Name ) und nicht um den Namen eines speziellen integrierten Dienstprogramms. Eine Implementierung kann andere Zeichen in einem Funktionsnamen als Erweiterung zulassen. Die Implementierung muss separate Namensräume für Funktionen und Variablen verwalten.

Und:

3.235 Name

In der Shell-Befehlssprache ein Wort, das ausschließlich aus Unterstrichen, Ziffern und Alphabeten aus dem tragbaren Zeichensatz besteht. Das erste Zeichen eines Namens ist keine Ziffer.

Hinweis: Der tragbare Zeichensatz wird ausführlich im tragbaren Zeichensatz definiert.

Ein Wort, das mit einer Ziffer beginnt, kann also kein Funktionsname sein.

muru
quelle
Trotzdem sagt POSIX nicht ganz warum, aber ich nehme es als Antwort "Weil Standards". Vielen Dank
Sergiy Kolodyazhnyy
4
@SergiyKolodyazhnyy Ich würde sagen, es ist eine geerbte Sache. Dieser Standard für Namen ist auch in anderen Bereichen ziemlich verbreitet (IIRC C-Namen folgen ebenfalls demselben Standard), daher handelt es sich wahrscheinlich um ein Unix-Ding. In C ist es auch einfacher zu analysieren
muru
3
@muru in C würde es einige Unklarheiten bringen, wenn es erlaubt wäre. ZB was würde 1Lbedeuten? Ein Funktionsname? Oder ein long intwörtliches?
Ruslan
2
Hinzu kommt, dass in C ein bloßer Funktionsname als Zeiger auf diese Funktion dienen kann. Auf diese Weise können Sie Funktionen als Parameter an eine Funktion übergeben, Verweise darauf in Variablen speichern usw. Wird häufig für Rückrufe verwendet. Dies steht im Gegensatz zum Namen der Funktion, gefolgt von ()möglicherweise darin enthaltenen Argumenten, die einen Aufruf der betreffenden Funktion bezeichnen (und den Wert annehmen, der von der aufgerufenen Funktion zurückgegeben wird). Wenn Sie also eine Funktion int f() { return 42; }in C haben, fist diese in einem Zeigerkontext gültig und in einem Ganzzeigerkontext f()ohne Zeiger.
Ein Lebenslauf vom
13

Dies ist in vielen Sprachen ein Standard, um Verwechslungen zwischen mathematischen Operationen und Variablen oder Funktionen oder Methoden zu vermeiden.

Erwägen:

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

Wie Sie sehen können, kann das spätere Ausführen von Mathematik in einem Programm sehr verwirrend werden, wenn Zahlen als Variablen- oder Funktionsnamen zulässig sind, und Sie müssten kreative Problemumgehungen finden, wenn Sie später tatsächlich mit diesen Zahlen rechnen müssen. In einigen Sprachen kann es auch zu unerwarteten Ergebnissen kommen. Stellen Sie sich vor, Sie erhöhen eine Zahl für eine Schleife, aber eine der Ziffern ist bereits eine Variable, die einer Zeichenfolge entspricht. Es würde sofort einen Fehler auslösen. Wenn Sie nicht der ursprüngliche Autor des Codes waren, kann es eine Weile dauern, bis dieser Fehler gefunden ist.

Kurz gesagt, aus diesem Grund können Sie in den meisten Sprachen keine Zahl als Namen einer Variablen, Funktion, Methode usw. verwenden.

Josh
quelle
Ich wollte kommentieren, "aber Variablen in der Shell müssen vorangestellt werden, $um erweitert zu werden", aber wenn die Shell von anderen Sprachen inspiriert ist, ist das in Ordnung, denke ich, und in arithmetischen Erweiterungsvariablen ((müssen keine führenden Variablen vorhanden sein $. OK, ich kann das verstehen
Sergiy Kolodyazhnyy
3
Ja, es ist eine Konvention, weil sie in fast jeder Sprache zu unerwarteten Ergebnissen führt, aber selbst in einer Situation, in der sie funktionieren würde, kann es für jeden, der nach Ihnen an Ihrem Code arbeiten müsste, sehr schwierig sein, Code zu verstehen.
Josh
2
@SergiyKolodyazhnyy arithmetische Erweiterung ermöglicht das Verweisen auf Variablennamen ohne $, also gibt es das. Aber das ist wahrscheinlich zweitrangig gegenüber dem anderen Grund, "nur der allgemeinen Konvention zu
folgen
@hobbs yep, stimme dem absolut zu
Sergiy Kolodyazhnyy
1
Diese Erklärung der "meisten Sprachen" macht für Muscheln wenig Sinn. Alle Bourne-style Schalen haben Parameter , deren Namen aussehen Zahlenliterale oder Operatoren: 0für die Shell oder Skriptnamen 1, 2..., für Positionsparameter, *für sie verbunden sind , -für die aktivierten Optionen, ?für den letzten Exit - Status, und !für die PID des letzten asynchronen Jobs. (Also auch in $(( ))die $oft benötigt werden .) Der hier gezeigte Code die vorgeschlagene Begründung zu demonstrieren ist kein Skript für jede Bourne - Shell-Stil, da gibt es keine Möglichkeit , es so zu zeigen, wie sie nicht gelten zu Sie.
Eliah Kagan
10

Betrachten Sie in C einen Ausdruck wie:

1000l + 2.0f;

Ist 1000leine Variable oder eine Konstante? Da Variablennamen nicht mit einer Ziffer beginnen können, muss sie eine Konstante sein. Dies macht das Parsen einfacher und strenger (Tippfehler wie 1000kkönnen leicht abgefangen werden). Es ist auch einfacher, eine einzige Regel für Variablen und Funktionsnamen zu haben, da Funktionen auch als Variablen behandelt werden können. Jetzt sind Parser natürlich viel komplexer und leistungsfähiger, und wir haben Dinge wie benutzerdefinierte Literale in C ++. Aber in jenen alten Tagen der Vorgeschichte könnte ein Opfer unnötiger Flexibilität Ihre Kompilierungs- (oder Interpretations-) Zeiten viel kürzer machen (und die Leute beschweren sich immer noch über C ++ - Kompilierungszeiten).

Und Sie können die Auswirkungen eines C-Einflusses in der gesamten Shell-Sprache sehen. Es ist daher nicht verwunderlich, dass die Bourne-Shell (oder C-Shell) und damit POSIX die Klasse der zulässigen Namen auf die gleiche wie die von C beschränkt hat.

Olorin
quelle
2
Als Erklärungen gehen, ist dies die richtige. Es ist nicht so, dass die gleichen Überlegungen für alle Sprachen gelten oder dass Shells im Bourne-Stil eine ähnliche Syntax wie C haben, sondern dass die mit C verbundene Kultur stark war und Shell-Designer einige Garantien dafür entwickeln mussten, welche Bezeichner sein würden dürfen. Ich denke, dies könnte Beispiele für "Sie können die Auswirkungen eines C-Einflusses in der gesamten Shell-Sprache sehen" verwenden, da Ähnlichkeiten zwischen ihnen die Unterschiede nicht wirklich überwiegen (denken Sie beispielsweise darüber nach, welche Zahlen als wahr angesehen werden). Trotzdem ist diese Antwort richtig.
Eliah Kagan
@Eliah Die Zahlensache ist wohl auch eine direkte Folge der Exit-Status für Erfolg und Misserfolg in C, daher denke ich beim Schreiben von Shell-Tests eher an Erfolg und Misserfolg als an Wahr und Falsch. Sie haben Recht damit, dass viel Shell-Syntax nichts mit C zu tun hat, aber Beispiele sind die geschweiften Klammern, die Semikolons, das Kurzschließen &&und ||die mangelnde Unterstützung für die ASCII-Null in Strings.
Olorin