(C'est plus long que j'ai voulu; s'il vous plaît garder avec moi.)
La plupart des langues sont constitués de quelque chose qui s'appelle une "syntaxe": le langage est composé de plusieurs mots-clés définis, et la gamme complète des expressions que vous pouvez construire dans cette langue est construite à partir de cette syntaxe.
Par exemple, disons que vous avez un simple quatre-fonction arithmétique "langue" qui ne prend qu'un seul chiffre les nombres entiers en entrée et ignore complètement l'ordre des opérations (je vous ai dit que c'était un langage simple). Cette langue pourrait être défini par la syntaxe suivante:
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
À partir de ces trois règles, vous pouvez construire n'importe quel nombre d'un seul chiffre-saisie des expressions arithmétiques. Vous pouvez ensuite écrire un analyseur syntaxique pour cette syntaxe qui décompose tout d'entrée valide dans sa composante types ($expression
, $number
ou $operator
) et traite le résultat. Par exemple, l'expression 3 + 4 * 5
peut être décomposé comme suit:
// 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
Maintenant, nous avons une entièrement analysée de la syntaxe, dans notre langue, de l'expression d'origine. Une fois que nous avons cela, nous pouvons passer et d'écrire un analyseur de retrouver les résultats de toutes les combinaisons de $number $operator $number
, et cracher un résultat quand nous n'avons qu'un $number
à gauche.
Prendre note qu'il n'existe pas $expression
des constructions de gauche dans la dernière version analysée de notre expression originale. C'est parce qu' $expression
peut toujours être réduit à une combinaison d'autres choses dans notre langue.
PHP est un peu la même: les constructions de langage sont reconnus comme l'équivalent de notre - $number
ou $operator
. Ils ne peuvent être réduits dans d'autres constructions de langage; au lieu de cela, ils sont les unités de base à partir de laquelle la langue est construit. La principale différence entre les fonctions et les constructions de langage, c'est que l'analyseur traite directement avec les constructions de langage. Il simplifie les fonctions dans les constructions de langage.
La raison que les constructions de langage peut ou ne peut pas exiger des parenthèses et la raison pour laquelle certains ont des valeurs de retour tandis que d'autres ne dépend entièrement sur les détails techniques de l'analyseur PHP, la mise en œuvre. Je ne suis pas bien versé dans la façon dont l'analyseur fonctionne, donc je ne peux pas répondre à ces questions, mais imaginez une seconde une langue qui commence par:
$expression := ($expression) | ...
Effectivement, cette langue est libre de prendre toutes les expressions qu'il trouve et de se débarrasser de l'entourage des parenthèses. PHP (et ici, je suis employant pure conjecture) peuvent avoir recours à quelque chose de similaire pour ses constructions de langage: print("Hello")
pourrait se réduit vers le bas pour print "Hello"
avant d'être analysée, ou vice-versa (la définition de la langue peut ajouter entre parenthèses, ainsi que de se débarrasser d'eux).
C'est la racine de pourquoi vous ne pouvez pas redéfinir les constructions de langage comme echo
ou print
: ils sont effectivement codé en dur dans l'analyseur, alors que les fonctions sont associées à un ensemble de constructions d'un langage et de l'analyseur vous permet de la modifier de la cartographie à la compilation ou à l'exécution pour le remplacer par votre propre ensemble de constructions de langage ou des expressions.
À la fin de la journée, la différence entre les constructions et les expressions est ceci: les constructions de langage sont compris et pris en considération par l'analyseur. Les fonctions intégrées, tandis que fournis par le langage, sont cartographiés et simplifié à un ensemble de constructions de langage avant l'analyse.
Plus d'infos:
-
Backus-Naur form, la syntaxe utilisée pour définir des langages formels (yacc utilise ce formulaire)
Edit: lu quelques-uns des autres réponses, les gens font des bons points. Parmi eux:
- Une langue builtin est plus rapide à l'appel à une fonction. C'est vrai, si seulement légèrement, parce que le PHP n'a pas besoin de carte que la fonction du langage-builtin équivalents avant l'analyse. Sur une machine moderne, cependant, la différence est assez négligeable.
- Une langue builtin contourne la vérification des erreurs. Cela peut ou peut ne pas être vrai, selon le PHP internes de mise en œuvre pour chaque builtin. Il est certainement vrai que, le plus souvent, les fonctions sont plus avancé de vérification des erreurs et d'autres fonctionnalités que les builtins ne le font pas.
- Les constructions de langage ne peut pas être utilisé en tant que fonction de rappels. C'est vrai, car une construction n'est pas une fonction. Ils sont des entités distinctes. Lorsque l'on code un builtin, vous n'êtes pas coder une fonction qui prend comme arguments - la syntaxe de la fonction est gérée directement par l'analyseur, et est reconnu comme un builtin, plutôt qu'une fonction. (Cela peut être plus facile à comprendre si vous envisagez de langues avec la première classe de fonctions: effectivement, vous pouvez passer des fonctions autour des objets. Vous ne pouvez pas le faire avec les builtins.)