В чем разница между конструкцией языка и встроенной функцией в PHP?

Я знаю, что include , isset , require , print , echo и некоторые другие не являются функциями, а языковыми конструкциями.

Некоторые из этих языковых конструкций требуют скобок, другие – нет.

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

У некоторых есть возвращаемое значение, другие – нет.

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

Итак, какова внутренняя разница между конструкцией языка и встроенной функцией?

Solutions Collecting From Web of "В чем разница между конструкцией языка и встроенной функцией в PHP?"

(Это длиннее, чем я предполагал, пожалуйста, несите меня.)

Большинство языков составлено из того, что называется синтаксисом: язык состоит из нескольких четко определенных ключевых слов, и полный набор выражений, которые вы можете построить на этом языке, создается из этого синтаксиса.

Например, предположим, что у вас есть простой четырехфункциональный арифметический «язык», который принимает только однозначные целые числа в качестве входных данных и полностью игнорирует порядок операций (я сказал вам, что это простой язык). Этот язык можно определить с помощью синтаксиса:

 // The | means "or" and the := represents definition $expression := $number | $expression $operator $expression $number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 $operator := + | - | * | / 

Из этих трех правил вы можете построить любое число арифметических выражений с одноразрядным входом. Затем вы можете написать синтаксический анализатор для синтаксиса, который разбивает любой допустимый ввод на его типы компонентов ( $expression $number , $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 и выплюнуть результат, когда у нас осталось только один $number .

Обратите внимание, что в окончательной анализируемой версии нашего исходного выражения не осталось никаких выражений. Это потому, что $expression всегда можно свести к сочетанию других вещей на нашем языке.

PHP очень похож: языковые конструкции распознаются как эквивалент нашего $operator $number или $operator . Они не могут быть сведены к другим языковым конструкциям ; вместо этого они являются базовыми единицами, из которых выстраивается язык. Ключевое различие между функциями и языковыми конструкциями таково: парсер напрямую занимается языковыми конструкциями. Он упрощает функции в языковых конструкциях.

Причина, по которой языковые конструкции могут содержать или не содержать скобки, и причина, по которой некоторые имеют возвращаемые значения, а другие не полностью зависят от конкретных технических деталей реализации парсера PHP. Я не настолько хорошо разбираюсь в том, как работает парсер, поэтому я не могу конкретно ответить на эти вопросы, но представьте себе второй язык, который начинается с этого:

 $expression := ($expression) | ... 

Эффективно этот язык свободен принимать любые выражения, которые он находит, и избавляться от окружающих круглых скобок. PHP (и здесь я использую чистые догадки) может использовать что-то подобное для своих языковых конструкций: print("Hello") может быть уменьшен до print "Hello" перед его анализом или наоборот (определения языка могут добавлять скобки как а также избавиться от них).

Это корень причины, по которой вы не можете переопределять языковые конструкции, такие как echo или print : они эффективно жестко закодированы в синтаксический анализатор, тогда как функции сопоставляются с набором языковых конструкций, и синтаксический анализатор позволяет вам изменять это сопоставление при компиляции или чтобы заменить собственный набор языковых конструкций или выражений.

В конце дня внутренняя разница между конструкциями и выражениями такова: языковые конструкции понимаются и обрабатываются парсером. Встроенные функции, предоставляемые языком, сопоставляются и упрощаются до набора языковых конструкций перед разбором.

Больше информации:

  • Форма Backus-Naur , синтаксис, используемый для определения формальных языков (yacc использует эту форму)

Редактирование: прочитав некоторые другие ответы, люди делают хорошие очки. Среди них:

  • Язык, на который встроен язык, быстрее, чем функция. Это верно, если только незначительно, потому что интерпретатору PHP не нужно сопоставлять эту функцию с его эквивалентами, основанными на языке, до разбора. Однако на современной машине разница довольно незначительна.
  • Встроенный язык обходит проверку ошибок. Это может быть или не быть правдой, в зависимости от внутренней реализации PHP для каждого встроенного. Конечно, верно, что чаще всего функции будут иметь более расширенную проверку ошибок и другие функции, которые не имеют встроенных функций.
  • Языковые конструкции не могут использоваться как обратные вызовы функций. Это верно, потому что конструкция не является функцией . Это отдельные сущности. При кодировании встроенного кода вы не кодируете функцию, которая принимает аргументы – синтаксис встроенного обрабатывается непосредственно анализатором и распознается как встроенный, а не как функция. (Это может быть проще понять, если вы рассматриваете языки с первоклассными функциями: эффективно, вы можете передавать функции как объекты. Вы не можете делать это со встроенными функциями.)

Языковые конструкции предоставляются самим языком (например, такие как «if», «while», …); отсюда их имя.

Одним из следствий этого является то, что они быстрее запускаются, чем предопределенные или определяемые пользователем функции (или так я слышал / читал несколько раз)

Я понятия не имею, как это делается, но одно, что они могут сделать (из-за того, что оно интегрировано непосредственно в langage) – это «обход» какого-то механизма обработки ошибок. Например, isset () может использоваться с несуществующими переменными без каких-либо уведомлений, предупреждений или ошибок.

 function test($param) {} if (test($a)) { // Notice: Undefined variable: a } if (isset($b)) { // No notice } 

* Обратите внимание, что это не относится к конструкциям всех языков.

Другое различие между функциями и языковыми конструкциями состоит в том, что некоторые из них можно вызывать без скобок, например ключевое слово.

Например :

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

Здесь тоже не для всех языковых конструкций.

Я полагаю, нет абсолютно никакого способа «отключить» конструкцию языка, потому что она является частью самого языка. С другой стороны, множество «встроенных» функций PHP не являются встроенными, поскольку они предоставляются расширениями, так что они всегда активны (но не все)

Другое отличие состоит в том, что языковые конструкции не могут использоваться как «указатели на функции» (например, обратные вызовы):

 $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 

У меня нет другой идеи, которая приходит мне на ум прямо сейчас … и я не очень разбираюсь в внутренних функциях PHP … Так что это будет прямо сейчас ^^

Если вы не получите здесь много ответов, возможно, вы могли бы спросить об этом внутренним спискам рассылки (см. http://www.php.net/mailing-lists.php ), где есть много PHP-разработчиков PHP; это те, кто, вероятно, знал бы об этом. ^^

(И меня действительно интересуют другие ответы, btw ^^)

В качестве ссылки: список ключевых слов и языковых конструкций в PHP

После прошивки кода я обнаружил, что php анализирует некоторые из операторов в файле yacc. Так что это особые случаи.

(см. Zend / zend_language_parser.y)

Кроме того, я не думаю, что есть другие различия.

Вы можете переопределить встроенные функции . Ключевые слова навсегда.