(これは私が意図したよりも長いです。ご容赦ください。)
ほとんどの言語は「構文」と呼ばれるもので構成されています。言語はいくつかの明確に定義されたキーワードで構成されており、その言語で構築できる式の完全な範囲はその構文から構築されます。
たとえば、1桁の整数のみを入力として受け取り、演算の順序を完全に無視する単純な4関数算術「言語」があるとします(単純な言語だと言いました)。その言語は次の構文で定義できます。
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
これらの3つのルールから、任意の数の1桁入力の算術式を作成できます。任意の有効な入力故障していることあなたは、その構成要素のタイプ(にこの構文のためのパーサを書くことができ$expression
、$number
または$operator
結果を含む)やお得な情報。たとえば、式3 + 4 * 5
は次のように分解できます。
// 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
これで、元の式に対して、定義済みの言語で完全に解析された構文が得られました。これを取得したら、パーサーを作成して、のすべての組み合わせの結果を見つけ、残り$number $operator $number
が1つだけの場合に結果を吐き出すことができます$number
。
$expression
元の式の最終的に解析されたバージョンには構成要素が残っていないことに注意してください。それ$expression
は、私たちの言語では常に他のものの組み合わせに還元できるからです。
PHPはほとんど同じです:言語構造は、当社の同等のものとして認識されています$number
か$operator
。それらを他の言語構造に還元することはできません。代わりに、それらは言語が構築される基本単位です。関数と言語構成要素の主な違いはこれです。パーサーは言語構成要素を直接扱います。関数を言語構造に単純化します。
言語構造が括弧を必要とする場合と必要としない場合の理由、および戻り値があるものとないものの理由は、PHPパーサー実装の特定の技術的な詳細に完全に依存しています。私はパーサーがどのように機能するかについてあまり詳しくないので、これらの質問に具体的に取り組むことはできませんが、これで始まる言語を少し想像してみてください。
$expression := ($expression) | ...
事実上、この言語は、見つけた表現を自由に取り、周囲の括弧を取り除くことができます。PHP(ここでは純粋な当て推量を採用しています)は、その言語構造に類似したものを採用しているprint("Hello")
可能性があります:print "Hello"
解析される前に削減されるか、またはその逆(言語定義で括弧を追加することも、括弧を取り除くこともできます)。
これがecho
orのような言語構成体を再定義できない理由の根本print
です:それらは効果的にパーサーにハードコードされていますが、関数は言語構成体のセットにマップされており、パーサーではコンパイル時または実行時にそのマッピングを変更できます独自の言語構成または式のセットで置き換えます。
結局のところ、構文と式の内部的な違いは次のとおりです。言語構文はパーサーによって理解され、処理されます。組み込み関数は、言語によって提供されますが、構文解析の前に、一連の言語構成にマップされ、単純化されます。
より詳しい情報:
編集:他のいくつかの答えを読んで、人々は良い点を作ります。その中で:
- 組み込み言語は、関数よりも呼び出しが高速です。PHPインタープリターは、構文解析の前にその関数を言語組み込みのものにマップする必要がないため、これはほんの少しでも当てはまります。しかし、最近のマシンでは、その違いはごくわずかです。
- 組み込み言語はエラーチェックをバイパスします。これは、各組み込みのPHP内部実装に応じて、正しい場合とそうでない場合があります。多くの場合、組み込み関数にはない高度なエラーチェックやその他の機能が関数にあることは確かです。
- 言語構造は関数コールバックとして使用できません。構成は関数ではないため、これは当てはまります。それらは別のエンティティです。組み込み関数をコーディングするときは、引数を取る関数をコーディングするのではなく、組み込み関数の構文はパーサーによって直接処理され、関数ではなく組み込み関数として認識されます。(これは、ファーストクラスの関数を備えた言語を考えると理解しやすいかもしれません。事実上、関数をオブジェクトとして渡すことができます。組み込み関数ではできません。)