Ich habe vor einiger Zeit mit einem neuen C ++ - Entwickler zusammengearbeitet, als er die Frage stellte: "Warum können Variablennamen nicht mit Zahlen beginnen?"
Ich konnte keine Antwort finden, außer dass einige Zahlen Text enthalten können (123456L, 123456U), und das wäre nicht möglich, wenn die Compiler denken würden, dass alles mit einer gewissen Anzahl von Alpha-Zeichen ein Variablenname ist.
War das die richtige Antwort? Gibt es noch weitere Gründe?
string 2BeOrNot2Be = "that is the question"; // Why won't this compile?
0
, das 0 auf den Stapel drückt. Eine andere ist0=
, die prüft, ob 0 auf dem Stapel ist.Antworten:
Denn dann wäre eine Ziffernfolge sowohl eine gültige Kennung als auch eine gültige Nummer.
quelle
A
- begannenF
und mit endetenh
. Stolperte mich, als ich zum ersten Mal versuchte, ein Label zu definieren, das auf die Musikdaten für Bachs zweiteilige Erfindung Nr. 13 verweist (logischer Name?Bach
).Denken Sie darüber nach:
Was ist ein? 2,0? oder 42?
Hinweis: Wenn Sie es nicht erhalten, bedeutet d nach einer Zahl die Zahl, bevor es sich um ein Doppelliteral handelt
quelle
d
ist kein gültiges schwebendes Literalsuffix in C ++. Floating-Literale sind standardmäßig Double- Literale. Sie können sie verwendenf
oderl
wenn Sie ein Float- oder ein Long-Double-Literal benötigen.Es ist jetzt eine Konvention, aber sie begann als technische Anforderung.
In früheren Zeiten erforderten Parser von Sprachen wie FORTRAN oder BASIC keine Verwendung von Leerzeichen. Grundsätzlich sind also folgende identisch:
und
Nehmen wir nun an, dass numerische Präfixe zulässig waren. Wie würden Sie das interpretieren?
wie
oder als
oder als
Das wurde also illegal gemacht.
quelle
DO 10 I=1,50
könnteDO1 0I=1,50
die Anweisung mehrdeutig analysiert werden als [übrigens, wenn man einen Punkt anstelle eines Kommas verwendet, wird die Anweisung zu einer Zuweisung zu a Gleitkommavariable benanntDO10I
.Weil Backtracking bei der lexikalischen Analyse beim Kompilieren vermieden wird. Eine Variable wie:
Der Compiler wird sofort wissen, dass es sich um eine Kennung handelt, wenn er auf den Buchstaben 'A' trifft.
Eine Variable wie:
Der Compiler kann erst entscheiden, ob es sich um eine Nummer oder eine Kennung handelt, wenn er auf "a" trifft, und muss daher zurückverfolgt werden.
quelle
Compiler / Parser / lexikalische Analysatoren waren für mich lange, lange her, aber ich denke, ich erinnere mich, dass es schwierig war, eindeutig zu bestimmen, ob ein numerisches Zeichen in der Kompilierungseinheit ein Literal oder eine Kennung darstellt.
Sprachen, in denen der Platz unbedeutend ist (wie ALGOL und das ursprüngliche FORTRAN, wenn ich mich richtig erinnere), konnten aus diesem Grund keine Zahlen akzeptieren, um mit Bezeichnern zu beginnen.
Dies geht weit zurück - vor speziellen Notationen zur Bezeichnung von Speicher oder numerischer Basis.
quelle
Ich bin damit einverstanden, dass es praktisch wäre, Kennungen mit einer Ziffer beginnen zu lassen. Ein oder zwei Personen haben erwähnt, dass Sie diese Einschränkung umgehen können, indem Sie Ihrer Kennung einen Unterstrich voranstellen, aber das ist wirklich hässlich.
Ich denke, ein Teil des Problems kommt von Zahlenliteralen wie 0xdeadbeef, die es schwierig machen, leicht zu merkende Regeln für Bezeichner zu finden, die mit einer Ziffer beginnen können. Eine Möglichkeit besteht darin, alles zuzulassen, was mit [A-Za-z _] + übereinstimmt und KEIN Schlüsselwort oder Zahlenliteral ist. Das Problem ist, dass es dazu führen würde, dass seltsame Dinge wie 0xdeadpork erlaubt werden, aber nicht 0xdeadbeef. Letztendlich denke ich, wir sollten fair zu allem Fleisch sein: P.
Als ich C zum ersten Mal lernte, erinnere ich mich, dass die Regeln für Variablennamen willkürlich und restriktiv waren. Am schlimmsten war, dass sie schwer zu merken waren, also gab ich es auf, sie zu lernen. Ich habe einfach getan, was sich richtig anfühlte, und es hat ziemlich gut funktioniert. Jetzt, wo ich viel mehr gelernt habe, scheint es nicht so schlimm zu sein, und ich habe es endlich richtig gelernt.
quelle
Es ist wahrscheinlich eine Entscheidung, die aus mehreren Gründen getroffen wurde. Wenn Sie das Token analysieren, müssen Sie nur das erste Zeichen überprüfen, um festzustellen, ob es sich um einen Bezeichner oder ein Literal handelt, und es dann zur Verarbeitung an die richtige Funktion senden. Das ist also eine Leistungsoptimierung.
Die andere Möglichkeit wäre, zu überprüfen, ob es sich nicht um ein Literal handelt, und die Domäne der Bezeichner als Universum abzüglich der Literale zu belassen. Aber um dies zu tun, müssten Sie jedes Zeichen jedes Tokens untersuchen, um zu wissen, wie man es klassifiziert.
Es gibt auch die stilistischen Implikationen, bei denen Identifikatoren Mnemonik sein sollen, sodass Wörter viel leichter zu merken sind als Zahlen. Als viele der Originalsprache geschrieben wurden, um die Stile für die nächsten Jahrzehnte festzulegen, dachten sie nicht daran, "bis" durch "2" zu ersetzen.
quelle
Variablennamen können nicht mit einer Ziffer beginnen, da dies zu folgenden Problemen führen kann:
Was ist der Wert von c? ist 4 oder ist 10!
ein anderes Beispiel:
ist die erste 5 eine Zahl oder ist ein Objekt (. Operator) Es gibt ein ähnliches Problem mit der zweiten 5.
Vielleicht gibt es noch andere Gründe. Daher sollten wir am Anfang eines Variablennamens keine Ziffer verwenden.
quelle
Die Verwendung einer Ziffer zum Beginnen eines Variablennamens erschwert die Fehlerprüfung beim Kompilieren oder Interpertieren erheblich.
Das Zulassen der Verwendung von Variablennamen, die wie eine Zahl begannen, würde den Sprachdesignern wahrscheinlich große Probleme bereiten. Wenn ein Compiler / Interpreter beim Parsen des Quellcodes auf ein Token stieß, das mit einer Ziffer begann, bei der ein Variablenname erwartet wurde, musste er ein riesiges, kompliziertes Regelwerk durchsuchen, um festzustellen, ob das Token wirklich eine Variable oder ein Fehler war . Die dem Sprachparser hinzugefügte zusätzliche Komplexität rechtfertigt diese Funktion möglicherweise nicht.
Soweit ich mich erinnern kann (ungefähr 40 Jahre), glaube ich nicht, dass ich jemals eine Sprache verwendet habe, die die Verwendung einer Ziffer zum Beginnen von Variablennamen erlaubte. Ich bin sicher, dass dies mindestens einmal gemacht wurde. Vielleicht hat jemand hier das tatsächlich irgendwo gesehen.
quelle
Wie mehrere Leute bemerkt haben, gibt es viel historisches Gepäck über gültige Formate für Variablennamen. Und Sprachdesigner werden immer von dem beeinflusst, was sie wissen, wenn sie neue Sprachen erstellen.
Das heißt, fast immer erlaubt eine Sprache nicht, dass Variablennamen mit Zahlen beginnen, weil dies die Regeln des Sprachdesigns sind. Oft liegt es daran, dass eine so einfache Regel das Parsen und Lexieren der Sprache erheblich erleichtert. Nicht alle Sprachdesigner wissen jedoch, dass dies der wahre Grund ist. Moderne Lexing-Tools helfen, denn wenn Sie versuchen, sie als zulässig zu definieren, erhalten Sie Analysekonflikte.
OTOH, wenn Ihre Sprache ein eindeutig identifizierbares Zeichen hat, um Variablennamen anzukündigen, können Sie es so einrichten, dass sie mit einer Zahl beginnen. Ähnliche Regelvarianten können auch verwendet werden, um Leerzeichen in Variablennamen zuzulassen. Aber die resultierende Sprache wird wahrscheinlich keiner populären konventionellen Sprache sehr ähnlich sein, wenn überhaupt.
Ein Beispiel für eine relativ einfache HTML-Vorlagensprache, bei der Variablen mit Zahlen beginnen und Leerzeichen enthalten können, finden Sie unter Qompose .
quelle
Denn wenn Sie zulassen, dass Schlüsselwort und Bezeichner mit numerischen Zeichen beginnen, kann der Lexer (Teil des Compilers) nicht ohne weiteres zwischen dem Beginn eines numerischen Literal und einem Schlüsselwort unterscheiden, ohne dass dies wesentlich komplizierter (und langsamer) wird.
quelle
Die Einschränkung ist willkürlich. Verschiedene Lisps erlauben es Symbolnamen, mit Ziffern zu beginnen.
quelle
Mit COBOL können Variablen mit einer Ziffer beginnen.
quelle
C ++ kann es nicht haben, weil die Sprachdesigner es zur Regel gemacht haben. Wenn Sie Ihre eigene Sprache erstellen würden, könnten Sie sie sicherlich zulassen, aber Sie würden wahrscheinlich auf dieselben Probleme stoßen wie sie und sich entscheiden, sie nicht zuzulassen. Beispiele für Variablennamen, die Probleme verursachen würden:
0x, 2d, 5555
quelle
Eines der Hauptprobleme bei der Lockerung syntaktischer Konventionen besteht darin, dass kognitive Dissonanzen in den Codierungsprozess eingeführt werden. Wie Sie über Ihren Code denken, könnte stark von der Unklarheit beeinflusst werden, die dies mit sich bringen würde.
War es nicht Dykstra, der sagte, dass der "wichtigste Aspekt eines Werkzeugs seine Wirkung auf seinen Benutzer ist"?
quelle
Wahrscheinlich, weil es dem Menschen leichter fällt, zu erkennen, ob es sich um eine Zahl oder eine Kennung handelt, und weil es Tradition ist. Identifikatoren, die mit einer Ziffer beginnen könnten, würden die lexikalischen Scans nicht allzu sehr erschweren.
Nicht alle Sprachen haben Bezeichner verboten, die mit einer Ziffer beginnen. In Forth konnten sie Zahlen sein, und kleine Ganzzahlen wurden normalerweise als Forth-Wörter (im Wesentlichen Bezeichner) definiert, da es schneller war, "2" als Routine zu lesen, um eine 2 auf den Stapel zu schieben, als "2" als Zahl zu erkennen dessen Wert 2 war. (Bei der Verarbeitung der Eingabe vom Programmierer oder vom Plattenblock teilte das Forth-System die Eingabe nach Leerzeichen auf. Es versuchte, das Token im Wörterbuch nachzuschlagen, um festzustellen, ob es sich um ein definiertes Wort handelte, und Wenn nicht, würde versucht, es in eine Zahl zu übersetzen, und wenn nicht, würde ein Fehler angezeigt.)
quelle
Angenommen, Sie haben zugelassen, dass Symbolnamen mit Zahlen beginnen. Angenommen, Sie möchten eine Variable 12345foobar benennen. Wie würden Sie dies von 12345 unterscheiden? Es ist eigentlich nicht besonders schwierig, mit einem regulären Ausdruck umzugehen. Das Problem ist eigentlich die Leistung. Ich kann nicht wirklich erklären, warum dies sehr detailliert ist, aber es läuft im Wesentlichen darauf hinaus, dass die Unterscheidung von 12345foobar von 12345 ein Backtracking erfordert. Dies macht den regulären Ausdruck nicht deterministisch.
Es ist eine viel bessere Erklärung dafür hier .
quelle
ifq
oderdoublez
aber nichtif
oder zuzulassendouble
? Das grundlegende Problem beim Zulassen, dass Bezeichner mit Ziffern beginnen, besteht darin, dass es vorhandene Formen von Hex-Literalen und Gleitkommazahlen gibt, die vollständig aus alphanumerischen Zeichen bestehen (Sprachen würden etwa $ 1234 oder h'1234 anstelle von 0x1234 verwenden und Zahlen wie 1E23, um einen Punkt einzuschließen, könnte dieses Problem vermeiden). Beachten Sie, dass Versuche, C erneut zu analysieren, bereits durch Dinge wie ausgelöst werden können0x12E+5
.Für einen Compiler ist es einfach, eine Variable mithilfe von ASCII am Speicherort anstelle der Nummer zu identifizieren.
quelle
Der Compiler hat 7 Phasen wie folgt:
Backtracking wird in der lexikalischen Analysephase beim Kompilieren des Codeteils vermieden. Die Variable wie Apple, der Compiler, erkennt ihre Kennung sofort, wenn sie in der lexikalischen Analysephase auf das Zeichen "A" trifft. Bei einer Variablen wie 123apple kann der Compiler jedoch erst dann entscheiden, ob es sich um eine Zahl oder einen Bezeichner handelt, wenn er auf 'a' trifft, und muss in der lexikalischen Analysephase zurückverfolgt werden, um festzustellen, ob es sich um eine Variable handelt. Es wird jedoch im Compiler nicht unterstützt.
Wenn Sie das Token analysieren, müssen Sie nur das erste Zeichen überprüfen, um festzustellen, ob es sich um einen Bezeichner oder ein Literal handelt, und es dann zur Verarbeitung an die richtige Funktion senden. Das ist also eine Leistungsoptimierung.
quelle
Ich denke, die einfache Antwort ist, dass es möglich ist, die Einschränkung ist sprachbasiert. In C ++ und vielen anderen ist dies nicht möglich, da die Sprache dies nicht unterstützt. Es ist nicht in die Regeln eingebaut, um dies zu ermöglichen.
Die Frage ist vergleichbar mit der Frage, warum der König im Schach nicht vier Felder gleichzeitig bewegen kann. Es ist, weil im Schach das ein illegaler Zug ist. Kann es in einem anderen Spiel sicher sein. Es kommt nur auf die Regeln an, nach denen gespielt wird.
quelle
Ursprünglich war es einfach so, weil es einfacher ist, sich Variablennamen als Zeichenfolgen anstatt als Zahlen zu merken (Sie können ihm mehr Bedeutung geben), obwohl Zahlen in die Zeichenfolge aufgenommen werden können, um die Bedeutung der Zeichenfolge zu verbessern oder die Verwendung desselben Variablennamens zu ermöglichen habe es als eine separate, aber enge Bedeutung oder einen Kontext bezeichnet. Zum Beispiel würden Schleife1, Schleife2 usw. Sie immer wissen lassen, dass Sie sich in einer Schleife befinden und / oder Schleife 2 eine Schleife innerhalb von Schleife1 ist. Welche würden Sie als Variable bevorzugen (hat mehr Bedeutung): Adresse oder 1121298? Welches ist leichter zu merken? Wenn die Sprache jedoch etwas verwendet, um anzuzeigen, dass es sich nicht nur um Text oder Zahlen handelt (z. B. die Adresse $ in $), sollte dies keinen Unterschied machen, da dies dem Compiler mitteilen würde, dass das Folgende als Variable behandelt werden soll ( in diesem Fall).
quelle
Die Variable kann vom Compiler auch während der Kompilierungszeit als Wert betrachtet werden, sodass der Wert den Wert immer wieder rekursiv aufrufen kann
quelle
Backtracking wird in der lexikalischen Analysephase beim Kompilieren des Codeteils vermieden . Die Variable wie Apple; Der Compiler erkennt seine Kennung sofort, wenn er in der lexikalischen Analysephase auf das Zeichen "A" trifft. Eine Variable wie 123apple; Der Compiler kann erst entscheiden, ob es sich um eine Zahl oder einen Bezeichner handelt, wenn er auf 'a' trifft und in der lexikalischen Analysephase ein Backtracking erforderlich ist, um festzustellen, ob es sich um eine Variable handelt. Es wird jedoch im Compiler nicht unterstützt.
Referenz
quelle
Es könnte nichts Falsches daran sein, wenn es darum geht, eine Variable zu deklarieren. Es gibt jedoch einige Unklarheiten, wenn versucht wird, diese Variable an einer anderen Stelle wie dieser zu verwenden:
let 1 = "Hallo Welt!" drucken (1) drucken (1)
print ist eine generische Methode, die alle Arten von Variablen akzeptiert. In dieser Situation weiß der Compiler nicht, auf welche (1) sich der Programmierer bezieht: die 1 des ganzzahligen Werts oder die 1, die einen Zeichenfolgenwert speichert. Vielleicht ist es für den Compiler in dieser Situation besser, so etwas zu definieren, aber wenn Sie versuchen, dieses mehrdeutige Material zu verwenden, bringen Sie einen Fehler mit Korrekturfunktion mit, um diesen Fehler zu beheben und diese Mehrdeutigkeit zu beseitigen.
quelle