(Isso é mais longo do que eu pretendia; por favor, tenha paciência.)
A maioria das linguagens é composta de algo chamado de "sintaxe": a linguagem é composta de várias palavras-chave bem definidas e a gama completa de expressões que você pode construir nessa linguagem é construída a partir dessa sintaxe.
Por exemplo, digamos que você tenha uma "linguagem" aritmética simples de quatro funções que aceita apenas inteiros de um dígito como entrada e ignora completamente a ordem das operações (eu disse que era uma linguagem simples). Essa linguagem pode ser definida pela sintaxe:
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
A partir dessas três regras, você pode construir qualquer número de expressões aritméticas de entrada de um dígito. Você pode então escrever um analisador para esta sintaxe que quebra qualquer entrada válida para seus tipos de componentes ( $expression
, $number
ou $operator
) e lida com o resultado. Por exemplo, a expressão 3 + 4 * 5
pode ser dividida da seguinte forma:
// 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
Agora temos uma sintaxe totalmente analisada, em nossa linguagem definida, para a expressão original. Assim que tivermos isso, podemos seguir e escrever um analisador para encontrar os resultados de todas as combinações de $number $operator $number
e cuspir um resultado quando tivermos apenas um $number
.
Observe que não há $expression
construções restantes na versão final analisada de nossa expressão original. Isso porque $expression
sempre pode ser reduzido a uma combinação de outras coisas em nossa língua.
PHP é praticamente o mesmo: construções de linguagem são reconhecidas como equivalentes a nosso $number
ou $operator
. Eles não podem ser reduzidos a outras construções de linguagem ; em vez disso, eles são as unidades básicas a partir das quais a linguagem é construída. A principal diferença entre funções e construções de linguagem é esta: o analisador lida diretamente com construções de linguagem. Ele simplifica funções em construções de linguagem.
O motivo pelo qual as construções de linguagem podem ou não exigir parênteses e o motivo pelo qual alguns têm valores de retorno enquanto outros não dependem inteiramente dos detalhes técnicos específicos da implementação do analisador PHP. Não sou muito versado em como o analisador funciona, então não posso responder a essas questões especificamente, mas imagine por um segundo uma linguagem que começa com isto:
$expression := ($expression) | ...
Efetivamente, esta linguagem é livre para pegar qualquer expressão que encontrar e se livrar dos parênteses circundantes. PHP (e aqui estou empregando pura suposição) pode empregar algo semelhante para suas construções de linguagem: print("Hello")
pode ser reduzido para print "Hello"
antes de ser analisado, ou vice-versa (as definições de linguagem podem adicionar parênteses e também eliminá-los).
Esta é a raiz da razão pela qual você não pode redefinir construções de linguagem como echo
ou print
: eles são efetivamente codificados no analisador, enquanto as funções são mapeadas para um conjunto de construções de linguagem e o analisador permite que você altere esse mapeamento em tempo de compilação ou execução para substitua seu próprio conjunto de construções ou expressões de linguagem.
No final do dia, a diferença interna entre construções e expressões é esta: construções de linguagem são compreendidas e tratadas pelo analisador. As funções integradas, embora fornecidas pela linguagem, são mapeadas e simplificadas para um conjunto de construções de linguagem antes da análise.
Mais informações:
Edit: Lendo algumas das outras respostas, as pessoas fazem bons pontos. Entre eles:
- Uma linguagem embutida é mais rápida de chamar do que uma função. Isso é verdade, mesmo que apenas marginalmente, porque o interpretador PHP não precisa mapear essa função para seus equivalentes integrados na linguagem antes de analisar. Em uma máquina moderna, entretanto, a diferença é bastante insignificante.
- Uma linguagem embutida ignora a verificação de erros. Isso pode ou não ser verdade, dependendo da implementação interna do PHP para cada integrado. Certamente é verdade que, na maioria das vezes, as funções terão verificação de erros mais avançada e outras funcionalidades que os internos não têm.
- Construções de linguagem não podem ser usadas como retornos de chamada de função. Isso é verdade, porque uma construção não é uma função . Eles são entidades separadas. Quando você codifica um builtin, não está codificando uma função que recebe argumentos - a sintaxe do builtin é tratada diretamente pelo analisador e é reconhecida como um builtin, em vez de uma função. (Isso pode ser mais fácil de entender se você considerar linguagens com funções de primeira classe: efetivamente, você pode passar funções como objetos. Você não pode fazer isso com builtins.)
As construções de linguagem são fornecidas pela própria linguagem (como instruções como "if", "while", ...); daí seu nome.
Uma consequência disso é que eles são mais rápidos de serem chamados do que funções predefinidas ou definidas pelo usuário (ou então eu ouvi / li várias vezes)
Não tenho ideia de como isso é feito, mas uma coisa que eles podem fazer (por estarem integrados diretamente ao idioma) é "ignorar" algum tipo de mecanismo de tratamento de erros. Por exemplo, isset () pode ser usado com variáveis não existentes sem causar qualquer aviso, aviso ou erro.
* Observe que não é o caso para as construções de todas as linguagens.
Outra diferença entre funções e construções de linguagem é que algumas delas podem ser chamadas sem parênteses, como uma palavra-chave.
Por exemplo :
Também aqui, não é o caso para todas as construções de linguagem.
Suponho que não haja absolutamente nenhuma maneira de "desabilitar" uma construção de linguagem porque ela faz parte da própria linguagem. Por outro lado, muitas funções PHP "integradas" não são realmente integradas porque são fornecidas por extensões de forma que estão sempre ativas (mas nem todas)
Outra diferença é que as construções de linguagem não podem ser usadas como "ponteiros de função" (quero dizer, retornos de chamada, por exemplo):
Não tenho nenhuma outra ideia vindo à minha mente agora ... e eu não sei muito sobre a parte interna do PHP ... Então é isso agora ^^
Se você não obtiver muitas respostas aqui, talvez possa perguntar isso para os internos da lista de discussão (consulte http://www.php.net/mailing-lists.php ), onde há muitos desenvolvedores principais de PHP; são eles que provavelmente sabem sobre essas coisas ^^
(E estou realmente interessado nas outras respostas, btw ^^)
Como referência: lista de palavras-chave e construções de linguagem em PHP
fonte
Depois de examinar o código, descobri que o php analisa algumas das instruções em um arquivo yacc. Portanto, são casos especiais.
(veja Zend / zend_language_parser.y)
Além disso, não creio que haja outras diferenças.
fonte
Você pode substituir as funções integradas . Palavras-chave são para sempre.
fonte