Metaprogramação - Metaprogramming

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 se modificar durante a execução. 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. Também permite que os programas tenham maior flexibilidade para lidar com novas situações com eficiência sem recompilação.

A metaprogramação pode ser usada para mover cálculos de tempo de execução para tempo de compilação , para gerar código usando cálculos de tempo de compilação e para habilitar código de auto-modificação . A habilidade de uma linguagem de programação de ser sua própria metalinguagem é chamada de reflexão . A reflexão é um recurso de linguagem valioso para facilitar a metaprogramação.

A metaprogramação era popular nas décadas de 1970 e 1980, usando linguagens de processamento de lista, como LISP . As máquinas de hardware LISP eram populares na década de 1980 e permitiam aplicativos que podiam processar código. Eles eram freqüentemente usados ​​para aplicações de inteligência artificial .

Abordagens

A metaprogramação permite que os desenvolvedores escrevam programas e desenvolvam códigos que se enquadram no paradigma de programação genérico . 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, uma vez que eles podem ser fornecidos como parâmetros quando usados.

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

  1. A primeira abordagem é expor as partes internas do mecanismo de tempo de execução para o código de programação por meio de interfaces de programação de aplicativos (APIs) como aquelas para o 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. Portanto, "programas podem escrever programas". Embora ambas as abordagens possam ser usadas no mesmo idioma, a maioria dos idiomas tende a se inclinar para um ou outro.
  3. A terceira abordagem é sair inteiramente da linguagem. Sistemas de transformação de programa 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 virtualmente qualquer idioma de destino, sem levar em consideração se esse idioma de destino tem suas próprias habilidades de metaprogramação. Pode-se ver isso em funcionamento 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.

Lisp é provavelmente a linguagem quintessencial 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 sem aspas (normalmente uma vírgula) introduz o código que é avaliado no tempo de definição do programa, e não no tempo de execução; consulte Formulários de autoavaliação e citações em Lisp . A linguagem de metaprogramação é, portanto, idêntica à linguagem de programação do host, e as rotinas Lisp existentes podem ser diretamente reutilizadas para metaprogramação, se desejado. Essa abordagem foi implementada em outras linguagens, incorporando um intérprete no programa, que trabalha diretamente com os dados do programa. Existem implementações desse tipo para algumas linguagens comuns de alto nível, como o Pascal Script for Object Pascal do RemObjects .

Usos

Geração de código

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

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

Este script (ou programa) gera um novo programa de 993 linhas que imprime os números 1–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.

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

Nem toda metaprogramação envolve programação generativa. Se os programas são modificáveis ​​em tempo de execução ou se a compilação incremental está 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 usar DSLs envolve metaprogramming generativa: lex e yacc , duas ferramentas utilizadas para gerar analisadores léxicos e analisadores , permitir que o usuário descrever o idioma usando expressões regulares e gramáticas livres de contexto , e incorporar os algoritmos complexos necessários para analisar com eficiência o língua.

Instrumentação de código

Um uso da metaprogramação é instrumentar programas para fazer uma análise dinâmica de programa .

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 para explorar possíveis patches para corrigir bugs.

Desafios

Alguns argumentam que existe uma curva de aprendizado acentuada para fazer uso completo dos recursos de metaprogramação. Uma vez que a metaprogramação oferece mais flexibilidade e capacidade de configuração 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 comum. 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 de 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ções desconhecidas ou resultados diferentes. Devido a isso, alguns acreditam que apenas desenvolvedores altamente qualificados devem trabalhar no desenvolvimento de recursos que exercem a metaprogramação em uma linguagem ou plataforma e os desenvolvedores médios devem aprender como usar esses recursos como parte da convenção.

Usos em linguagens de programação

Sistemas macro

Montadores de macro

O IBM / 360 e seus derivados tinham recursos poderosos de macro assembler que eram freqüentemente usados ​​para gerar programas completos em assembly 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 assembler que geravam instruções COBOL como uma etapa de pré-processamento.

Outros montadores, como MASM , também oferecem suporte a macros.

Metaclasses

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

Metaprogramação de template

Metaprogramação em estágios

Tipos dependentes

O uso de tipos dependentes permite provar que o código gerado nunca é inválido. 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 List of Program Transformation Systems .

Veja também

Referências

links externos