Uma das coisas que faz Ruby brilhar é a capacidade de criar melhor idiomas específicos de domínio, como
Embora se possa duplicar essas bibliotecas no LISP por meio de macro, acho que a implementação do Ruby é mais elegante. No entanto, acho que há casos em que a macro do LISP pode ser melhor que a do Ruby, embora eu não pudesse pensar em um.
Então, em que área a macro do LISP é melhor do que a "capacidade" de Ruby de criar DSL, se houver?
atualizar
Eu perguntei isso porque as linguagens de programação modernas estão se aproximando da singularidade do LISP , como
- C obteve pré-processador de expansão macro , embora muito primitivo e propenso a erros
- C # tem atributos, embora seja somente leitura, exposto por reflexão
- O Python adicionou o decorador, que pode modificar o comportamento da função (e classe para a v 3.0), embora pareça bastante limitado.
- Ruby TMTOWTDI que cria DSL elegante, se o cuidado for aplicado, mas de maneira Ruby.
Fiquei pensando se a macro do LISP é aplicável apenas a casos especiais e se os outros recursos da linguagem de programação são poderosos o suficiente para aumentar a abstração para enfrentar os desafios atuais do desenvolvimento de software.
Respostas:
Leia No Lisp e decida por si mesmo.
Meu resumo é que Ruby é melhor em fornecer sintaxe conveniente. Mas Lisp vence, sem dúvida, a capacidade de criar novas abstrações e, em seguida, colocar a abstração em camadas. Mas você precisa ver o Lisp na prática para entender esse ponto. Daí o livro recomendar.
fonte
But Lisp wins, hands down, at the ability to create new abstractions, and then to layer abstraction on abstraction.
Agora eu sei o porquê. . .As instalações do Ruby para criação de DSL não mudam a natureza do idioma. As instalações de metaprogramação do Ruby estão inerentemente ligadas à sintaxe e à semântica do Ruby, e o que quer que você escreva deve ser desviado para o modelo de objeto do Ruby.
Compare isso com Lisp (e Scheme, cujas macros são diferentes ), onde as macros operam no próprio programa abstrato. Como um programa Lisp é um valor Lisp, uma macro é uma função que mapeia uma sintaxe essencialmente arbitrária para outra.
Efetivamente, um DSL Ruby ainda se parece com Ruby, mas um DSL Lisp não precisa se sentir como Lisp.
fonte
Os DSLs de Ruby não são DSLs, e eu absolutamente odeio usá-los porque a documentação deles é sobre como eles realmente funcionam. Vamos pegar o ActiveRecord, por exemplo. Permite "declarar" associações entre modelos:
Mas a declaratividade desse "DSL" (como a
class
própria sintaxe do Ruby ) é uma mentira horrível que pode ser exposta por qualquer pessoa que entenda como o "DSLs" do Ruby realmente funciona:(Tente fazer algo parecido com isso no corpo de um
defclass
formulário Lisp !)Assim que você tem um código como o acima em sua base de código, todo desenvolvedor do projeto precisa entender completamente como DSLs do Ruby realmente funcionam (não apenas a ilusão que eles criam) antes de poderem manter o código. A documentação disponível será completamente inútil, porque documentam apenas o uso idiomático , o que preserva a ilusão declarativa.
O RSpec é ainda pior do que o acima, porque possui casos extremos bizarros que exigem extensa engenharia reversa para depuração. (Passei um dia inteiro tentando descobrir por que um dos meus casos de teste estava sendo ignorado. Verificou-se que o RSpec executa todos os casos de teste que têm contextos após casos de teste sem contexto, independentemente da ordem em que aparecem na origem , porque o
context
método coloca seu bloco em uma estrutura de dados diferente da que normalmente seria inserida.)As DSLs do Lisp são implementadas por macros, que são pequenos compiladores. As DSLs que você pode criar dessa maneira não são meros abusos da sintaxe existente do Lisp. Eles são mini-idiomas reais que podem ser escritos para serem completamente perfeitos, porque podem ter sua própria gramática. Por exemplo, a
LOOP
macro do Lisp é muito mais poderosa que oeach
método Ruby .(Eu sei que você já aceitou uma resposta, mas nem todo mundo que lê isso quer ler a totalidade do On Lisp .)
fonte