O que é um construtor da linguagem? – php característica-linguagem

Pergunta:


Em PHP, já li e ouvi várias vezes a respeito dos Construtores da Linguagem. Os casos que sempre ouvi falar deles foi em casos onde se dizia: “prefira usar X ao invés de Y, pois Y é uma função e X é um construtor da linguagem”.

Um dos casos que já li algo a respeito seria no caso de usar isset pra checar um índice de um array, ao invés de array_keys_exists (sei bem a diferença entre os dois, mas não é o foco da pergunta). A recomendação é porque array_key_exists é uma função, e isset, um construtor.

Sendo assim, eu queria saber algumas coisa:

  • O que seria um construtor da linguagem em PHP? Quais são eles?

  • Por que a documentação do PHP recomenda, em alguns casos, usar construtores da linguagem ao invés das funções?

  • Nos casos em que os construtores da linguagem se assemelham às funções (como isset, empty e require), quais são as principais diferenças entre os Construtores da linguagem e as funções?

Um exemplo da pergunta 2: usar isset ao invés de is_null (que é uma função), onde isset também retorna True caso o valor da variável seja NULL.

Autor da pergunta Wallace Maxters

Maniero

O que seria um construtor da linguagem em PHP? Quais são eles?

Alguns não gostarão disto, mas eu tenho que dizer que costuma ser gambiarra, pelo menos a maioria dos casos em PHP.

Tudo que o compilador trata de forma especial podemos considerar como construção da linguagem (não gosto do termo construtor aí porque ele não é bem um agente e sim uma característica, então vou usar construção). Uma função de forma geral é uma construção da linguagem, porque ela trata de forma especial. Digo, a criação de função em si é uma construção. O if é uma construção. Mas usar uma função é algo do usuário, mesmo que seja uma função padrão da biblioteca já não pertence à linguagem, a função não tem significado especial.

Por que a documentação do PHP recomenda, em alguns casos, usar construtores da linguagem ao invés das funções?

Acredito que por ela ter mais eficiência, ou porque já está pronto, ou porque é a única opção mesmo (depende do caso). De fato uma construção pode ser mais eficiente porque o compilador/interpretador pode tratar de forma melhor do que uma função poderia, mas em certas linguagens isso não ocorre ou não é necessário, ou o ganho é irrisório. Curiosamente linguagens de script, como é o caso de PHP, não precisam muito de otimizações e uma função seria adequada. Construções de linguagem podem ser úteis quando o compilador pode garantir um código target melhor. E curiosamente essas linguagens tem capacidade de otimizar funções a tal ponto que torna a construção desnecessária. Então podemos falar em falha do compilador do PHP também.

Embora hoje eu acho que tem muito disto por legado. Hoje talvez fariam diferente. Ou não, afinal em toda versão desta linguagem colocam coisas ruins novas.

Nos casos em que os construtores da linguagem se assemelham às funções (como isset, empty e require), quais são as principais diferenças entre os Construtores da linguagem e as funções?

O require eu acho que deve ser construção mesmo porque ele muda o código fonte que está sendo trabalhando ali, tem uma influência maior na execução, mas em PHP muda menos. Note que ele pode ser usado até sem parênteses, assim como o echo e outros assim podem ser usados sem.

Quem sabe o fato de não obrigar os parenteses tenha sido o motivo para preferir ser construção da linguagem. Tem linguagem que permite deixá-los de lado em alguns casos de funções sem que precise ser construção de linguagem.

O empty() por exemplo provavelmente pode ter alguma otimização porque ela trata de vários tipos e aí teria um enorme switch para selecionar a ação de acordo com o argumento usado e isto teria um custo, mesmo que nem sempre expressivo porque a maioria dos tipos estaria no início da tabela e e as verificações não são, ou não deveriam ser feitas uma a uma, mas vai saber se o switch do PHP não é otimizado assim.

O isset() pode ser porque envolve coisas internas da linguagem, mas poderia ser sim uma função.

O que seria um construtor da linguagem em PHP? Quais são eles?

O construtor da linguagem ou palavas reservadas são as gramáticas definidas /usadas pelo analisador léxico para interpretar uma sintaxe. Programas como lex/flex e yacc/bison que compõe esse universo de analise léxica. Por exemplo: Se você quiser escrever uma nova linguagem você terá que definir quais os comandos ela aceita ou não, em qual ordem dever ser escrito e definir cada detalhe para que o computador saiba interpretar os comandos e inclusive saber o que fazer quando algo estiver escrito na sua nova linguagem.

Suponhamos que você tenha definido entre outros as palavras (“procurar” e “negativar”), essas palavras serão reservadas. o lex/flex em conjunto yacc/bison trabalham para ler essas entradas e gerar um código em C já otimizado para reconhecer a sua sintaxe e trata-la conforme você definiu. O commando “isset” do php também é definido na gramatica da linguagem, mais especificamente em no arquivo zend_language_scanner.l o código fonte está disponível se desejar ter mais informações. Já a função “array_key_exists” ela não está presente do construtor léxico. Ela não é uma palavra reservada por não fazer da sintaxe (idioma) php, porém ela existe e agrega funcionalidades ao core do php e compõe o módulo standard do php , “array_key_exists” você pode achar mais informações no “php_array.h” e “array.c“, como pode ser observado ao contrário do isset que é definda na construção da sintaxe, ela não é definida na criação da linguagem, mas sim “adicionada” “PHP_FUNCTION(array_key_exists)”, assim como você pode poderia estar criando um módulo próprio e adicionando qualquer outra função.

Você pode encontrar alguns token usados no php direto no manual ou ainda no código fonte. Se desejar, pode também encontrar no próprio stackoverflow um post sobre análise léxica também tem muito material interessante sobre isso na internet.

Observação:

lex, flex, yacc e bison são programas diferentes. E inseridos no contexto apenas para facilitar, caso deseje obter mais referências sobre o assunto

Por que a documentação do PHP recomenda, em alguns casos, usar construtores da linguagem ao invés das funções?

No caso do isset e array_key_exists a recomendação que encontrei no site é devido à questões de performance, conforme na própria página da documentação do php, uma das sugestões não é de substituir, mas de usar ambos. Existe um Benchmark, mostrando o tempo de execução do algoritmos.

O motivo de um ser mais rápida do que a outra, não é exclusivamente o fato de uma ser um construtor de linguagem e outra ser uma função, mas também a complexidade do algoritmos para executar um isset ou um array_key_exists.

A complexidade do algoritmo pode fazer com que você ganhe ou perca desempenho dependendo do volume do uso. Como cada caso é um caso, o ideal é ler tanto a documentação quanto a nota para obter mais informação, e caso ainda reste dúvida, tenha necessidade e/ou interesse é possível ter acesso ao código fonte.

No isset e array_key_exists o que foi apontado foi o desempenho, porém podem ser questões desde de depreciação, retro compatibilidade e etc…,mas volto a dizer, cada caso é um caso.

A título de curiosidade essa é a implementação do array_key_exists no
php 7.1

PHP_FUNCTION(array_key_exists)
{
    zval *key;                  /* key to check for */
    HashTable *array;           /* array to check in */

    ZEND_PARSE_PARAMETERS_START(2, 2)
        Z_PARAM_ZVAL(key)
        Z_PARAM_ARRAY_OR_OBJECT_HT(array)
    ZEND_PARSE_PARAMETERS_END();

    switch (Z_TYPE_P(key)) {
        case IS_STRING:
            if (zend_symtable_exists_ind(array, Z_STR_P(key))) {
                RETURN_TRUE;
            }
            RETURN_FALSE;
        case IS_LONG:
            if (zend_hash_index_exists(array, Z_LVAL_P(key))) {
                RETURN_TRUE;
            }
            RETURN_FALSE;
        case IS_NULL:
            if (zend_hash_exists_ind(array, ZSTR_EMPTY_ALLOC())) {
                RETURN_TRUE;
            }
            RETURN_FALSE;

        default:
            php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
            RETURN_FALSE;
    }
}

Nos casos em que os construtores da linguagem se assemelham às funções (como isset, empty e require), quais são as principais diferenças entre os Construtores da linguagem e as funções?

Os “Construtores da linguagem” como citado anteriormente seriam a gramática da linguagem “consultar análisador léxico”. Já as funções “nesse caso” seriam outros recursos (funções) definidas em módulos e extensões do php.

Espero que isso te ajuda de alguma forma.

Fonte

Related Posts:

Qual a diferença entre AppCompatActivity e Activity? – android android-activity
Pergunta: Qual a diferença da AppCompatActivity para Activity ? A partir de qual versão a AppCompatActivity foi adicionada ao Android? Autor da pergunta Luhhh A diferença reside ...
Como abreviar palavras em PHP? – php string
Pergunta: Possuo informações comuns como nome de pessoas e endereços, e preciso que elas contenham no máximo 30 caracteres sem cortar palavras. Exemplo: 'Avenida Natalino João Brescansin' ...
Qual é a finalidade de um parêntese vazio numa declaração Lambda? – c# expressões-lambda característica-linguagem
Pergunta: Criei um exemplo de uma declaração Lambda sem argumentos, entretanto, estou com duvidas referente a omissão do parêntese vazio () na declaração. Veja o exemplo: class ...
Boas práticas para URI em API RESTful – api rest restful
Pergunta: Estou com dúvida em relação às URIs de alguns recursos da api que estou desenvolvendo. Tenho os recursos projetos e atividades com relação 1-N, ...
Dúvidas sobre a integração do MySQL com Java – java mysql netbeans
Pergunta: Estou criando um sistema no NetBeans, utilizando a linguagem Java e o banco de dados MySQL. Escrevi o seguinte código para realizar a conexão ...
Qual é a finalidade da pasta Model do framework Inphinit? – php inphinit
Pergunta: No Inphinit micro-framework existe a pasta Model que fica dentro da pasta application, e nela é onde ficam as classes, mas eu estou muito ...
Uso do ‘@’ em variáveis – javascript typescript coffeescript
Pergunta: Vejo em algumas linguagens que compilam para javascript, como TypeScript e CoffeeScript, o uso do @ em variáveis, como também, casos em que o ...
Qual tamanho máximo um arquivo JSON pode ter? – json arquivo
Pergunta: Vou dar um exemplo para conseguir explicar minha duvida: Preciso recuperar informação de imagens vindas de uma API, esse banco de imagens me retorna JSON's ...
O que é Teste de Regressão? – terminologia engenharia-de-software testes
Pergunta: Na matéria de Teste de Software o professor abordou um termo chamado Teste de Regressão, isto dentro da disciplina de teste de software. Sendo ...
Função intrínseca para converter numérico para string – cobol
Pergunta: Estou a tentar saber se existe alguma função intrínseca do COBOL para converter um data numérico para string sem precisar usar a cláusula REDEFINES: ( ...
Porque usar implements? – java android
Pergunta: Qual a diferença entre usar btn.setOnClickListener(new OnClickListener() { e public class MainActivity extends Activity implements OnClickListener{ Estive fazendo um curso de Android e meu professor falou que ...
O que é XHTML e quando deve ser usado? – html xml xhtml
Pergunta: O que eu sei é que o XHTML precisa ser XML válido. Isso implica, por exemplo, que todas as tags precisam ser fechadas. Por ...
Uma placa aceleradora de vídeo pode melhorar o desempenho não-gráfico? [fechada] – desempenho
Pergunta: Para desenvolver em Ruby on Rails, eu utilizo aqui uma máquina virtual do VirtualBox com Ubuntu Server 14.04 sem interface gráfica instalada. Recentemente descobri uma ...
Concat() VS Union() – c# .net
Pergunta: Qual a diferença entre Concat() e Union() ? Quando usar Concat() e quando usar Union() ? Somente pode ser usado em list ? ...
Como usar randômico no C++? – c++
Pergunta: Gostaria de um exemplo da utilização do randômico no C++, pois preciso utiliza-lo mas não sei como funciona. Autor da ...

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *