(Dies ist länger als beabsichtigt; bitte tragen Sie es mit mir.)
Die meisten Sprachen bestehen aus einer sogenannten "Syntax": Die Sprache besteht aus mehreren genau definierten Schlüsselwörtern, und der gesamte Ausdrucksbereich, den Sie in dieser Sprache erstellen können, wird aus dieser Syntax aufgebaut.
Nehmen wir zum Beispiel an, Sie haben eine einfache arithmetische "Sprache" mit vier Funktionen, die nur einstellige Ganzzahlen als Eingabe verwendet und die Reihenfolge der Operationen vollständig ignoriert (ich habe Ihnen gesagt, dass es sich um eine einfache Sprache handelt). Diese Sprache könnte durch die Syntax definiert werden:
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
Aus diesen drei Regeln können Sie eine beliebige Anzahl von einstelligen arithmetischen Eingaben erstellen. Anschließend können Sie einen Parser für diese Syntax , dass bricht jede gültige Eingabe in seine Komponententypen (schreiben $expression
, $number
oder $operator
) und beschäftigt sich mit dem Ergebnis. Beispielsweise kann der Ausdruck 3 + 4 * 5
wie folgt unterteilt werden:
// Parentheses used for ease of explanation; they have no true syntactical meaning
$expression = 3 + 4 * 5
= $expression $operator (4 * 5) // Expand into $exp $op $exp
= $number $operator $expression // Rewrite: $exp -> $num
= $number $operator $expression $operator $expression // Expand again
= $number $operator $number $operator $number // Rewrite again
Jetzt haben wir eine vollständig analysierte Syntax in unserer definierten Sprache für den ursprünglichen Ausdruck. Sobald wir dies haben, können wir einen Parser schreiben, um die Ergebnisse aller Kombinationen von zu finden $number $operator $number
, und ein Ergebnis ausspucken, wenn wir nur noch eines $number
haben.
Beachten Sie, dass $expression
in der endgültigen analysierten Version unseres ursprünglichen Ausdrucks keine Konstrukte mehr vorhanden sind . Das liegt daran, dass $expression
sich unsere Sprache immer auf eine Kombination anderer Dinge reduzieren lässt.
PHP ist ähnlich: Sprachkonstrukte werden als das Äquivalent unserer erkannt $number
oder$operator
. Sie können nicht auf andere Sprachkonstrukte reduziert werden ; Stattdessen sind sie die Basiseinheiten, aus denen die Sprache aufgebaut ist. Der Hauptunterschied zwischen Funktionen und Sprachkonstrukten besteht darin, dass der Parser sich direkt mit Sprachkonstrukten befasst. Es vereinfacht Funktionen zu Sprachkonstrukten.
Der Grund, warum Sprachkonstrukte Klammern erfordern oder nicht, und der Grund, warum einige Rückgabewerte haben, während andere nicht vollständig von den spezifischen technischen Details der PHP-Parser-Implementierung abhängen. Ich bin nicht so gut mit der Funktionsweise des Parsers vertraut, daher kann ich diese Fragen nicht speziell beantworten, aber stellen Sie sich für eine Sekunde eine Sprache vor, die damit beginnt:
$expression := ($expression) | ...
Tatsächlich kann diese Sprache alle gefundenen Ausdrücke verwenden und die umgebenden Klammern entfernen. PHP (und hier verwende ich reine Vermutungen) verwendet möglicherweise etwas Ähnliches für seine Sprachkonstrukte:print("Hello")
möglicherweise auf reduziertprint "Hello"
bevor es analysiert wird, oder umgekehrt (Sprachdefinitionen können Klammern hinzufügen und sie entfernen).
Dies ist die Wurzel dafür, warum Sie Sprachkonstrukte wie nicht neu definieren können echo
oderprint
: Sie sind effektiv im Parser fest codiert, während Funktionen einer Reihe von Sprachkonstrukten zugeordnet sind und der Parser es Ihnen ermöglicht, diese Zuordnung zur Kompilierungs- oder Laufzeit auf zu ändern Ersetzen Sie Ihre eigenen Sprachkonstrukte oder Ausdrücke.
Letztendlich besteht der interne Unterschied zwischen Konstrukten und Ausdrücken darin, dass Sprachkonstrukte vom Parser verstanden und behandelt werden. Integrierte Funktionen werden, obwohl sie von der Sprache bereitgestellt werden, vor dem Parsen einer Reihe von Sprachkonstrukten zugeordnet und vereinfacht.
Mehr Info:
- Backus-Naur-Form , die Syntax zur Definition formaler Sprachen (yacc verwendet diese Form)
Bearbeiten: Beim Lesen einiger anderer Antworten machen die Leute gute Punkte. Unter ihnen:
- Eine eingebaute Sprache ist schneller aufzurufen als eine Funktion. Dies ist, wenn auch nur am Rande, der Fall, da der PHP-Interpreter diese Funktion vor dem Parsen nicht seinen in die Sprache integrierten Entsprechungen zuordnen muss. Bei einer modernen Maschine ist der Unterschied jedoch vernachlässigbar gering.
- Eine eingebaute Sprache umgeht die Fehlerprüfung. Dies kann zutreffen oder nicht, abhängig von der internen PHP-Implementierung für jedes eingebaute Gerät. Es ist sicherlich richtig, dass Funktionen häufig über eine erweiterte Fehlerprüfung und andere Funktionen verfügen, die integrierte Funktionen nicht bieten.
- Sprachkonstrukte können nicht als Funktionsrückrufe verwendet werden. Dies ist wahr, weil ein Konstrukt keine Funktion ist . Sie sind getrennte Einheiten. Wenn Sie eine integrierte Funktion codieren, codieren Sie keine Funktion, die Argumente akzeptiert. Die Syntax der integrierten Funktion wird direkt vom Parser verarbeitet und als integrierte Funktion und nicht als Funktion erkannt. (Dies ist möglicherweise leichter zu verstehen, wenn Sie Sprachen mit erstklassigen Funktionen betrachten: Sie können Funktionen effektiv als Objekte weitergeben. Mit integrierten Funktionen können Sie dies nicht tun.)
Sprachkonstrukte werden von der Sprache selbst bereitgestellt (wie Anweisungen wie "if", "while", ...); daher ihr Name.
Eine Folge davon ist, dass sie schneller aufgerufen werden können als vordefinierte oder benutzerdefinierte Funktionen (oder so habe ich mehrmals gehört / gelesen).
Ich habe keine Ahnung, wie es gemacht wird, aber eine Sache, die sie tun können (weil sie direkt in die Sprache integriert sind), ist, eine Art Fehlerbehandlungsmechanismus zu "umgehen". Zum Beispiel kann isset () mit nicht vorhandenen Variablen verwendet werden, ohne dass eine Benachrichtigung, Warnung oder ein Fehler verursacht wird.
* Beachten Sie, dass dies nicht bei allen Konstrukten der Fall ist.
Ein weiterer Unterschied zwischen Funktionen und Sprachkonstrukten besteht darin, dass einige davon wie ein Schlüsselwort ohne Klammern aufgerufen werden können.
Zum Beispiel :
Auch hier ist dies nicht bei allen Sprachkonstrukten der Fall.
Ich nehme an, es gibt absolut keine Möglichkeit, ein Sprachkonstrukt zu "deaktivieren", da es Teil der Sprache selbst ist. Andererseits sind viele "eingebaute" PHP-Funktionen nicht wirklich eingebaut, da sie von Erweiterungen bereitgestellt werden, sodass sie immer aktiv sind (aber nicht alle).
Ein weiterer Unterschied besteht darin, dass Sprachkonstrukte nicht als "Funktionszeiger" verwendet werden können (ich meine beispielsweise Rückrufe):
Ich habe momentan keine andere Idee ... und ich weiß nicht viel über die Interna von PHP ... Also das wird es jetzt sein ^^
Wenn Sie hier nicht viele Antworten erhalten, können Sie dies möglicherweise an die Mailinglisten-Interna (siehe http://www.php.net/mailing-lists.php ) richten, wo es viele PHP-Kernentwickler gibt. sie sind diejenigen, die wahrscheinlich über dieses Zeug Bescheid wissen würden ^^
(Und ich bin wirklich interessiert an den anderen Antworten, übrigens ^^)
Als Referenz : Liste der Schlüsselwörter und Sprachkonstrukte in PHP
quelle
Nachdem ich den Code durchgesehen habe, habe ich festgestellt, dass PHP einige Anweisungen in einer Yacc-Datei analysiert. Es handelt sich also um Sonderfälle.
(siehe Zend / zend_language_parser.y)
Abgesehen davon glaube ich nicht, dass es andere Unterschiede gibt.
quelle
Sie können integrierte Funktionen überschreiben . Schlüsselwörter sind für immer.
quelle