(思ったより長くなりましたが、ご容赦ください。)
ほとんどの言語は「構文」と呼ばれるもので構成されています。言語はいくつかの明確に定義されたキーワードで構成されており、その言語で作成できる式の完全な範囲はその構文から構築されています。
たとえば、入力として 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
orと同等のものとして認識されます$operator
。それらを他の言語構造に還元することはできません。代わりに、それらは言語が構築される基本単位です。関数と言語構造の主な違いは次のとおりです。パーサーは言語構造を直接扱います。関数を言語構造に単純化します。
言語構造が括弧を必要とする場合と必要としない場合がある理由、および戻り値を持つものとそうでないものがある理由は、PHP パーサー実装の特定の技術的詳細に完全に依存します。私はパーサーがどのように機能するかについてあまり詳しくないので、これらの質問に具体的に答えることができませんが、これで始まる言語をちょっと想像してみてください:
$expression := ($expression) | ...
事実上、この言語は、見つけた式を自由に取り、周囲の括弧を取り除くことができます。PHP (ここでは純粋な当て推量を採用しています) は、その言語構成体に似たようなものを採用している可能性があります:解析される前にprint("Hello")
削減されるprint "Hello"
か、またはその逆です (言語定義は括弧を追加したり削除したりできます)。
echo
これが、 orのような言語構造を再定義できない理由の根源print
です: 関数は言語構造のセットにマップされ、パーサーはコンパイル時または実行時にそのマッピングを独自の言語構造または式のセットに置き換えます。
結局のところ、構造と式の内部的な違いは次のとおりです。言語構造はパーサーによって理解され、処理されます。組み込み関数は、言語によって提供されますが、解析前に一連の言語構造にマップされ、単純化されます。
より詳しい情報:
編集:他の回答のいくつかを読んで、人々は良い点を指摘します。その中で:
- 言語ビルトインは、関数よりも呼び出しが高速です。PHP インタープリターは、解析する前にその関数を言語組み込みの対応する関数にマップする必要がないため、これはほんのわずかではありますが、当てはまります。ただし、最新のマシンでは、違いはほとんどありません。
- 組み込み言語はエラー チェックをバイパスします。これは、各ビルトインの PHP 内部実装に応じて、真である場合とそうでない場合があります。多くの場合、関数には組み込み関数にはないより高度なエラー チェック機能やその他の機能が備わっていることは確かです。
- 言語構造は、関数のコールバックとして使用できません。構造体は関数ではないため、これは真です。それらは別個のエンティティです。ビルトインをコーディングするときは、引数を取る関数をコーディングしているのではありません。ビルトインの構文はパーサーによって直接処理され、関数ではなくビルトインとして認識されます。(ファーストクラスの関数を持つ言語を考えると、これは理解しやすいかもしれません。事実上、関数をオブジェクトとして渡すことができます。ビルトインではそれを行うことはできません。)