Metaprogramação

Da Wikipédia, a enciclopédia livre
Ir para a navegação Saltar para pesquisar

Metaprogramação é uma técnica de programação na qual os programas de computador têm a capacidade de tratar outros programas como seus dados. Isso significa que um programa pode ser projetado para ler, gerar, analisar ou transformar outros programas e até mesmo modificar a si mesmo durante a execução. [1] [2] Em alguns casos, isso permite que os programadores minimizem o número de linhas de código para expressar uma solução, reduzindo o tempo de desenvolvimento. [3] Também permite flexibilidade ao criador de programas para lidar eficientemente com novas situações sem recompilação.

A metaprogramação pode ser usada para mover cálculos do tempo de execução para o tempo de compilação , para gerar código usando cálculos de tempo de compilação e para habilitar código automodificável . A capacidade de uma linguagem de programação ser sua própria metalinguagem é chamada de reflexão . [4] A reflexão é um recurso valioso da linguagem para facilitar a metaprogramação.

A metaprogramação era popular nas décadas de 1970 e 1980 usando linguagens de processamento de listas como LISP . Máquinas de hardware LISP eram populares na década de 1980 e habilitavam aplicativos que podiam processar código. Eles eram frequentemente usados ​​para aplicações de inteligência artificial .

Abordagens

A metaprogramação permite que os desenvolvedores escrevam programas e desenvolvam código que se enquadre no paradigma de programação genérica . Ter a própria linguagem de programação como um tipo de dados de primeira classe (como em Lisp , Prolog , SNOBOL ou Rebol ) também é muito útil; isso é conhecido como homoiconicidade . A programação genérica invoca um recurso de metaprogramação dentro de uma linguagem, permitindo escrever código sem a preocupação de especificar tipos de dados, pois eles podem ser fornecidos como parâmetros quando usados.

A metaprogramação geralmente funciona de três maneiras. [5]

  1. A primeira abordagem é expor os componentes internos do mecanismo de tempo de execução ao código de programação por meio de interfaces de programação de aplicativos (APIs) como a do emissor .NET IL .
  2. A segunda abordagem é a execução dinâmica de expressões que contêm comandos de programação, geralmente compostos de strings, mas também podem ser de outros métodos usando argumentos ou contexto, como Javascript. [6] Assim, "programas podem escrever programas". Embora ambas as abordagens possam ser usadas na mesma linguagem, a maioria das linguagens tende a se inclinar para uma ou outra.
  3. A terceira abordagem é sair completamente da linguagem. Sistemas de transformação de programas de propósito geral , como compiladores, que aceitam descrições de linguagem e realizam transformações arbitrárias nessas linguagens, são implementações diretas de metaprogramação geral. Isso permite que a metaprogramação seja aplicada a praticamente qualquer linguagem-alvo, independentemente de essa linguagem-alvo ter alguma habilidade de metaprogramação própria. Pode-se ver isso no trabalho com Scheme e como ele permite lidar com algumas limitações enfrentadas em C usando construções que faziam parte da própria linguagem Scheme para estender C. [7]

Lisp é provavelmente a linguagem por excelência com facilidades de metaprogramação, tanto por causa de sua precedência histórica quanto por causa da simplicidade e poder de sua metaprogramação. Na metaprogramação Lisp, o operador unquote (normalmente uma vírgula) introduz o código que é avaliado no tempo de definição do programa em vez de no tempo de execução; consulte Formulários de autoavaliação e cotação em Lisp . A linguagem de metaprogramação é, portanto, idêntica à linguagem de programação do host, e as rotinas Lisp existentes podem ser reutilizadas diretamente para metaprogramação, se desejado. Essa abordagem foi implementada em outras linguagens, incorporando um interpretador no programa, que trabalha diretamente com os dados do programa. Existem implementações desse tipo para algumas linguagens comuns de alto nível, como RemObjects' Script Pascal para Object Pascal .

Usos

Geração de código

Um exemplo simples de metaprograma é este script POSIX Shell , que é um exemplo de programação generativa :

#!/bin/sh 
# metaprograma 
echo  '#!/bin/sh' > program
 for i in  $( seq 992 ) 
do 
    echo  "echo $i " >> program
 done
chmod +x programa

Este script (ou programa) gera um novo programa de 993 linhas que imprime os números de 1 a 992. Esta é apenas uma ilustração de como usar código para escrever mais código; não é a maneira mais eficiente de imprimir uma lista de números. No entanto, um programador pode escrever e executar este metaprograma em menos de um minuto e terá gerado mais de 1000 linhas de código nesse período de tempo.

Um quine é um tipo especial de metaprograma que produz seu próprio código-fonte como saída. Quines são geralmente de interesse apenas recreativo ou teórico.

Nem toda metaprogramação envolve programação generativa. Se os programas forem modificáveis ​​em tempo de execução ou se a compilação incremental estiver disponível (como em C# , Forth , Frink , Groovy , JavaScript , Lisp , Elixir , Lua , Nim , Perl , PHP , Python , REBOL , Ruby , Rust , SAS , Smalltalk , e Tcl ), então as técnicas podem ser usadas para realizar a metaprogramação sem realmente gerar o código-fonte.

Um estilo de abordagem generativa é empregar linguagens específicas de domínio (DSLs). Um exemplo bastante comum de uso de DSLs envolve metaprogramação generativa: lex e yacc , duas ferramentas usadas para gerar analisadores e analisadores léxicos , permitem que o usuário descreva a linguagem usando expressões regulares e gramáticas livres de contexto e incorpore os algoritmos complexos necessários para analisar eficientemente a linguagem Língua.

Instrumentação de código

Um uso da metaprogramação é instrumentar programas para fazer análises dinâmicas de programas .

Mudanças comportamentais

A metaprogramação pode ser usada para tecer mudanças comportamentais em um programa, como feito na programação orientada a aspectos . Por exemplo, a metaprogramação pode ser usada para injetar sinalizadores de recursos ou explorar possíveis patches para corrigir bugs. [8]

Desafios

Alguns argumentam que há uma curva de aprendizado acentuada para fazer uso completo dos recursos de metaprogramação. [9] Como a metaprogramação oferece mais flexibilidade e configurabilidade em tempo de execução, o uso indevido ou incorreto da metaprogramação pode resultar em erros injustificados e inesperados que podem ser extremamente difíceis de depurar para um desenvolvedor médio. Pode introduzir riscos no sistema e torná-lo mais vulnerável se não for usado com cuidado. Alguns dos problemas comuns que podem ocorrer devido ao uso incorreto da metaprogramação são a incapacidade do compilador de identificar parâmetros de configuração ausentes, dados inválidos ou incorretos podem resultar em exceção desconhecida ou resultados diferentes. [10] Devido a isso, alguns acreditam [9]que apenas desenvolvedores altamente qualificados devem trabalhar no desenvolvimento de recursos que exercitam metaprogramação em uma linguagem ou plataforma e desenvolvedores médios devem aprender como usar esses recursos como parte da convenção.

Usos em linguagens de programação

Sistemas de macros

Montadores de macros

O IBM/360 e seus derivados tinham recursos poderosos de montagem de macros que eram frequentemente usados ​​para gerar programas completos em linguagem assembly [ carece de fontes ] ou seções de programas (para diferentes sistemas operacionais, por exemplo). As macros fornecidas com o sistema de processamento de transações CICS tinham macros de montagem que geravam instruções COBOL como uma etapa de pré-processamento.

Outros montadores, como MASM , também suportam macros.

Metaclasses

As metaclasses são fornecidas pelas seguintes linguagens de programação:

Metaprogramação de templates

Metaprogramação encenada

Tipos dependentes

O uso de tipos dependentes permite provar que o código gerado nunca é inválido. [15] No entanto, essa abordagem é de ponta e raramente é encontrada fora das linguagens de programação de pesquisa.

Implementações

A lista de sistemas de metaprogramação notáveis ​​é mantida em Lista de Sistemas de Transformação de Programas .

Veja também

Referências

  1. ^ Harald Sondergaard. "Curso de Análise e Transformação de Programas" . Recuperado em 18 de setembro de 2014 .
  2. ^ Czarnecki, Krzysztof ; Eisenecker, Ulrich W. (2000). Programação Gerativa . ISBN 0-201-30977-7.
  3. ^ Walker, Max. "A Arte da Metaprogramação em Java" . Novo Círculo . Recuperado em 28 de janeiro de 2014 .
  4. ^ Krauss, Aaron. "Conceitos de Programação: Introspecção e Reflexão de Tipos" . A Sociedade . Recuperado em 14 de setembro de 2014 .
  5. ^ Joshi, Prateek (5 de abril de 2014). "O que é Metaprogramação? - Parte 2/2" . Enigma Perpétuo . Recuperado em 14 de agosto de 2014 .
  6. ^ por exemplo, instance_eval em Ruby recebe uma string ou uma função anônima. "Rdoc for Class: BasicObject (Ruby 1.9.3) - instance_eval" . Recuperado em 30 de dezembro de 2011 .
  7. ^ "Arte da Metaprogramação" .
  8. ^ Durieux, Thomas; Cornu, Benoit; Seinturier, Lionel; Monperrus, Martin (2017). "Geração de patch dinâmico para exceções de ponteiro nulo usando metaprogramação" (PDF) . 2017 IEEE 24th International Conference on Software Analysis, Evolution and Reengineering (SANER) . IEEE: 349-358. arXiv : 1812.00409 . doi : 10.1109/SANER.2017.7884635 . ISBN  978-1-5090-5501-2. S2CID  2736203 .
  9. ^ a b Brigando, Ian. "O desafio da metaprogramação" . IanBicking.org . Recuperado em 21 de setembro de 2016 .
  10. Terry, Matt (21 de agosto de 2013). "Cuidado com Metaprogramação" . Medium . com . Corporação Média . Recuperado em 21 de agosto de 2014 .
  11. ^ Atravésdo "Meta Object Protocol" do Common Lisp Object System
  12. ^ Lisp (linguagem de programação) "Formulários de autoavaliação e citações", operador de quase aspas.
  13. ^ "LMS: Geração de Programas e Compiladores Embutidos em Scala" . scala-lms.github.io . Recuperado 2017-12-06 .
  14. ^ Rompf, Tiark; Odersky, Martin (junho de 2012). "Lightweight Modular Staging: Uma Abordagem Pragmática para Geração de Código em Tempo de Execução e DSLs Compiladas" . Comum. ACM . 55 (6): 121–130. doi : 10.1145/2184319.2184345 . ISSN 0001-0782 . S2CID 52898203 .  
  15. ^ Chlipala, Adam (junho de 2010). "Ur: metaprogramação estaticamente tipada com computação de registro de nível de tipo" (PDF) . Avisos ACM SIGPLAN . PLDI '10. 45 (6): 122–133. doi : 10.1145/1809028.1806612 . Recuperado em 29 de agosto de 2012 .

Links externos