Was ist der Unterschied zwischen einem Sprachkonstrukt und einer "integrierten" Funktion in PHP?


92

Ich weiß , dass include, isset, require, print, echo, und einige andere sind keine Funktionen , sondern Sprachkonstrukte.

Einige dieser Sprachkonstrukte benötigen Klammern, andere nicht.

require 'file.php';
isset($x);

Einige haben einen Rückgabewert, andere nicht.

print 'foo'; //1
echo  'foo'; //no return value

Was ist also der interne Unterschied zwischen einem Sprachkonstrukt und einer integrierten Funktion?

Antworten:


131

(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, $numberoder $operator) und beschäftigt sich mit dem Ergebnis. Beispielsweise kann der Ausdruck 3 + 4 * 5wie 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 $numberhaben.

Beachten Sie, dass $expressionin der endgültigen analysierten Version unseres ursprünglichen Ausdrucks keine Konstrukte mehr vorhanden sind . Das liegt daran, dass $expressionsich 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.)

2
Eine großartige Antwort, die offen genug ist, um auf viele Sprachen angewendet zu werden, nicht nur auf PHP. Danke dir!
Levi Botelho

15

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.

function test($param) {}
if (test($a)) {
    // Notice: Undefined variable: a
}

if (isset($b)) {
    // No notice
}

* 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 :

echo 'test'; // language construct => OK

function my_function($param) {}
my_function 'test'; // function => Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING

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):

$a = array(10, 20);

function test($param) {echo $param . '<br />';}
array_map('test', $a);  // OK (function)

array_map('echo', $a);  // Warning: array_map() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name

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


Sie können eine Funktion haben, die eine nicht festgelegte Variable akzeptiert, ohne einen Hinweis zu generieren, indem Sie die Variable als Referenz verwenden. Dies ist nicht auf Sprachkonstrukte wie isset () beschränkt.
Tom Haigh

Oh, darüber habe ich nicht nachgedacht :-( Danke!
Pascal MARTIN

4

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.


1

Sie können integrierte Funktionen überschreiben . Schlüsselwörter sind für immer.


Das ist keine eingebaute Funktion. Wird in der APD-Erweiterung (Advanced PHP Debugger) definiert.
Ionuț G. Stan

Über das Überschreiben von Funktionen könnten Sie eine Beute in der Runkit-Erweiterung haben (es ist auch kein Kern, es ist eine Erweiterung, also antworten Sie nicht auf das OP, sondern nur auf diese Antwort). Es ist wirklich mächtig und neuer als APD (und ich glaube, ich habe vor einiger Zeit gehört, dass einige Leute noch daran arbeiten, auch wenn es nicht auf pecl.php.net gezeigt wird)
Pascal MARTIN
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.