Wenn Sie eine Sprache lernen, haben Sie wahrscheinlich das Wort „Syntax“ gehört und beschäftigen sich ständig damit. (Verdammter Syntaxfehler).
Vor ein paar Nächten dachte ich mir, ich habe Programmierparadigmen und -techniken nie ernsthaft verfolgt, und heute habe ich angefangen, aus den kleinsten Themen zu lernen, die ich immer höre (auch wenn ich mich schon daran erinnere). Ich habe dieses Repository erstellt. Der von mir gewählte Lernpfad ist charakteristisch (in der Datei LEARNING_LIST.md). Lassen Sie uns mal durchgehen: Im Gegensatz zu den natürlichen Sprachen, mit denen wir unsere Gedanken und Gefühle kommunizieren, können Programmiersprachen als künstliche Sprachen betrachtet werden, die von Männern und Frauen ursprünglich für die Kommunikation mit Computern, aber ebenso wichtig für die Kommunikation von Algorithmen zwischen Menschen definiert wurden .
Sprachdefinitionen bestehen beispielsweise aus drei Komponenten:
Syntax: Die Syntax einer Programmiersprache ist der Satz von Regeln, die die Kombinationen von Symbolen definieren, die als korrekt strukturierte Programme in dieser Sprache gelten. Die Syntax einer Sprache definiert ihre Oberflächenform. Textbasierte Programmiersprachen basieren auf Zeichenfolgen. Die lexikalische Grammatik einer Textsprache legt fest, wie Zeichen in Tokens aufgeteilt werden müssen. Die Syntax bezieht sich auf die Art und Weise, wie Symbole kombiniert werden können, um wohlgeformte Sätze (oder Programme) in der Sprache zu erstellen. Die Syntax definiert die formalen Beziehungen zwischen den Bestandteilen einer Sprache und liefert so eine strukturelle Beschreibung der verschiedenen Ausdrücke, aus denen zulässige Zeichenfolgen in der Sprache bestehen. Die Syntax befasst sich ausschließlich mit der Form und Struktur von Symbolen in einer Sprache, ohne dass deren Bedeutung berücksichtigt wird. Syntax ist das Konzept, das sich nur darauf bezieht, ob der Satz für die Grammatik der Sprache gültig ist oder nicht.
Semantik: Bei der Semantik geht es darum, ob der Satz eine gültige Bedeutung hat oder nicht. Die Semantik offenbart die Bedeutung syntaktisch gültiger Zeichenfolgen in einer Sprache. Für natürliche Sprachen bedeutet dies, Sätze und Phrasen mit den Objekten, Gedanken und Gefühlen unserer Erfahrungen in Beziehung zu setzen. Bei Programmiersprachen beschreibt die Semantik das Verhalten, dem ein Computer folgt, wenn er ein Programm in der Sprache ausführt. Wir könnten dieses Verhalten offenlegen, indem wir die Beziehung zwischen der Eingabe und Ausgabe eines Programms beschreiben oder indem wir Schritt für Schritt erklären, wie ein Programm auf einer realen oder abstrakten Maschine ausgeführt wird. Semantik ist der Oberbegriff für die Bedeutungslehre. In der Informatik zielt das Fachgebiet der Semantik von Programmiersprachen darauf ab, Programmen eine präzise mathematische Bedeutung zu geben.
In natürlichen Sprachen kann ein Satz grammatikalisch korrekt, aber semantisch bedeutungslos sein. Zum Beispiel der Satz:
"Der Mann hat die Unendlichkeit im Laden gekauft."
Das ist grammatikalisch korrekt, ergibt aber in der realen Welt keinen Sinn. Ebenso kann in Programmiersprachen eine Anweisung syntaktisch korrekt, aber semantisch falsch sein, weil sie gegen die Regeln der Sprache oder deren beabsichtigte Bedeutung verstößt.
Bei der Semantik auf niedriger Ebene der Programmierung geht es uns darum, ob eine Anweisung mit korrekter Syntax auch gemäß dem Typsystem der Sprache oder anderen Regeln sinnvoll ist. Auch wenn die Syntax gültig sein könnte, könnte die semantische Bedeutung der Operation ungültig sein. Das Typsystem in statisch typisierten Sprachen wie Java hilft dabei, diese Regeln vor der Laufzeit durchzusetzen, aber dynamisch typisierte Sprachen wie JavaScript erzwingen diese Regeln nicht immer bis zur Laufzeit.
In JavaScript, das lose typisiert ist, verfügen Sie möglicherweise nicht über den Schutz, der mit einem strengeren Typsystem einhergeht, und die Sprache lässt bestimmte Operationen zu, die semantisch keinen Sinn ergeben. Betrachten Sie den folgenden JavaScript-Code:
let name = "Alice"; name = 42; // No error, but semantically this doesn't make sense.
Hier ist die Syntax vollkommen gültig und JavaScript erlaubt die Zuweisung, aber semantisch ist sie seltsam. Sie versuchen, einer Variablen eine Zahl (42) zuzuweisen, die vermutlich eine Zeichenfolge (Name) enthalten soll. In JavaScript gibt es keine Typprüfung, die Sie vor diesem Fehler schützt, aber es handelt sich um einen semantischen Fehler auf niedriger Ebene, da er nicht mit der Absicht des Entwicklers übereinstimmt.
Wenn wir es umsetzen. Es wird ausgeführt. ohne Fehler!
In strengeren Sprachen wie TypeScript oder Java würde dies sofort während der Kompilierung einen Typfehler auslösen.
TypeScript, eine Obermenge von JavaScript, führt eine Typprüfung ein, um diese semantischen Probleme auf niedriger Ebene zu verhindern:
let name: string = "Alice"; name = 42; // Error: Type 'number' is not assignable to type 'string'.
In TypeScript erkennt der Compiler den semantischen Fehler, weil 42 eine Zahl ist und keiner als String deklarierten Variablen zugewiesen werden kann. Diese Durchsetzung von Typen schützt den Entwickler vor unbeabsichtigten Fehlern.
Um diese semantischen Probleme auf niedriger Ebene zu vermeiden, verwenden Entwickler in JavaScript häufig Laufzeitprüfungen:
let name = "Alice"; if (typeof name !== "string") { throw new Error("Expected a string!"); }
Auch wenn JavaScript keine Typen erzwingt, kann das Hinzufügen manueller Prüfungen dazu beitragen, Fehler zu vermeiden, bei denen falsche Typen zu Problemen im Programm führen.
Auf einer höheren Ebene beschäftigt sich die Semantik damit, was Ihr Programm erreichen soll. Es geht nicht nur darum, ob das Programm eine gültige Syntax hat oder ob die Typen korrekt ausgerichtet sind – es geht darum, ob sich das Programm so verhält, wie es der Entwickler beabsichtigt hat, oder das Problem löst, für das es entwickelt wurde.
Angenommen, Sie bauen ein einfaches Aktienhandelssystem auf. Bei der High-Level-Semantik Ihres Codes geht es darum, sicherzustellen, dass das System Aktien auf die richtige Art und Weise und mit der richtigen Geschäftslogik handelt. Auch wenn der Code keine Typ- oder Syntaxfehler erzeugt, kann es sein, dass er die beabsichtigte Funktionalität nicht erfüllt.
Sehen wir uns ein JavaScript-Beispiel für High-Level-Semantik anhand eines vereinfachten Aktienhandelsszenarios an:
let openTrade = { symbol: "EURUSD", direction: "buy", profit: 100 }; function closeTrade(trade) { if (trade.profit >= 50) { console.log(`Closing trade for ${trade.symbol} with profit of ${trade.profit}`); } else { console.log(`Trade for ${trade.symbol} is not ready to close.`); } } // Check if a trade is open for EURUSD and close it if the profit target is reached. closeTrade(openTrade);
Die Syntax ist korrekt und das Programm läuft fehlerfrei. Stellen Sie sich jedoch vor, dass wir jetzt auf einer höheren Ebene einen Fehler einführen, beispielsweise versehentlich zwei Trades für dasselbe Symbol eingeben, was gegen die Geschäftsregeln des Systems verstößt.
let openTrades = [ { symbol: "EURUSD", direction: "buy", profit: 100 }, { symbol: "EURUSD", direction: "sell", profit: 20 } ]; // Check all trades and close any that hit their profit target. openTrades.forEach(trade => closeTrade(trade));
Hier werden beide Trades unabhängig voneinander verarbeitet, aber das System erhält am Ende zwei Trades auf demselben Symbol, einen in Kaufrichtung und einen in Verkaufsrichtung. Dies verstößt gegen die Geschäftsregel auf hoher Ebene, dass wir zu einem bestimmten Zeitpunkt nur einen offenen Trade pro Symbol haben sollten.
Obwohl der Code ohne Syntax- oder Typfehler ausgeführt wird, ist er auf hoher Ebene semantisch falsch. Die Systemlogik hätte sicherstellen sollen, dass jeweils nur ein Trade pro Symbol aktiv sein kann. Dieser Fehler würde in einem realen Handelssystem wahrscheinlich zu unbeabsichtigten Folgen führen, beispielsweise zu finanziellen Verlusten.
Um dieses semantische Problem auf hoher Ebene zu beheben, müssen Sie die Logik anpassen, um sicherzustellen, dass nur ein Trade für ein bestimmtes Symbol offen ist:
let openTrades = [ { symbol: "EURUSD", direction: "buy", profit: 100 } ]; function openNewTrade(newTrade) { // Ensure no other trades are open for the same symbol. const existingTrade = openTrades.find(trade => trade.symbol === newTrade.symbol); if (!existingTrade) { openTrades.push(newTrade); console.log(`Opened new trade for ${newTrade.symbol}`); } else { console.log(`Cannot open a new trade for ${newTrade.symbol}, trade already exists.`); } } openNewTrade({ symbol: "EURUSD", direction: "sell", profit: 0 });
Hier stellt die Logik sicher, dass kein neuer Handel eröffnet werden kann, wenn bereits ein aktiver Handel für dasselbe Symbol besteht. Dies ist eine semantische Korrektur auf hoher Ebene, da sie die Kerngeschäftslogik anspricht, der das Programm folgen soll, und nicht ein Syntax- oder Typproblem.
Dies waren nur grundlegende Informationen zu jedem. Weitere Informationen finden Sie in den folgenden Artikeln:
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3