Esquema vs Lisp comum: quais características fizeram a diferença no seu projeto? [fechadas]


155

Não há escassez de perguntas vagas sobre "Esquema vs Lisp comum" no StackOverflow e neste site, por isso quero tornar este mais focado. A pergunta é para pessoas que codificaram nos dois idiomas:

Ao codificar no Scheme, de quais elementos específicos da sua experiência em codificação Common Lisp você sentiu mais falta? Ou, inversamente, ao codificar no Common Lisp, o que você perdeu ao codificar no Scheme?

Não quero dizer necessariamente apenas recursos de linguagem. A seguir, todos os itens válidos a serem perdidos, no que diz respeito à pergunta:

  • Bibliotecas específicas.
  • Recursos específicos de ambientes de desenvolvimento como SLIME, DrRacket etc.
  • Recursos de implementações específicas, como a capacidade do Gambit de gravar blocos de código C diretamente na fonte do Scheme.
  • E, claro, recursos de linguagem.

Exemplos do tipo de resposta que espero:

  • "Eu estava tentando implementar o X no Common Lisp, e se eu tivesse as continuações de primeira classe de Scheme, eu simplesmente teria feito Y, mas, em vez disso, eu tinha que fazer Z, o que era mais doloroso".
  • "O script do processo de construção no meu projeto Scheme ficou cada vez mais doloroso à medida que minha árvore de origem cresceu e eu vinculei cada vez mais bibliotecas C. Para o meu próximo projeto, voltei ao Common Lisp."
  • "Eu tenho uma grande base de código C ++ existente e, para mim, ser capaz de incorporar chamadas C ++ diretamente no meu código do Gambit Scheme valia totalmente quaisquer deficiências que o Scheme possa ter em relação ao Common Lisp, mesmo incluindo a falta de suporte ao SWIG".

Então, espero histórias de guerra, em vez de sentimentos gerais como "O esquema é uma linguagem mais simples" etc.


25
Uma pergunta excelente e bem formulada. Eu mesmo sou curioso; espero que haja algumas pessoas com experiência em ambos os idiomas, dispostas a fornecer algumas dicas.
Robert Harvey

1
@ Josh K - é claramente responsável, mas não há necessariamente uma única resposta definitiva. Só que eu aposto que haverá uma, porque alguém sairá com uma resposta tão impressionante que todo mundo é como whoa!
glenatron

4
@ Josh: Então talvez você não esteja familiarizado com o Scheme e o Common Lisp. Ambos os idiomas são muito poderosos por si só, e ainda não têm aceitação convencional. Por que é isso? Pode ser porque existem muitos dialetos; Qual você escolhe? Uma comparação desse tipo pode ser muito esclarecedora, e o OP elaborou cuidadosamente a pergunta para limitar o escopo às respostas que, na minha opinião, são muito específicas e responsáveis.
Robert Harvey

13
Gente, não feche a pergunta apenas porque você não gosta ou não pode se relacionar com ela. É claramente uma pergunta "real"; se você não encontrar um motivo melhor para fechá-lo, não deverá votar para fechá-lo.
Robert Harvey

4
Você poderia enviar um e-mail para Richard Stallman para obter sua resposta.
Wassimans

Respostas:


100

Minha graduação era em Ciência Cognitiva e Inteligência Artificial. A partir disso, tive uma introdução de um curso ao Lisp. Eu pensei que a linguagem era interessante (como em "elegante"), mas realmente não pensei muito nisso até que me deparei com a Décima Regra de Greenspun muito mais tarde:

Qualquer programa C ou Fortran suficientemente complicado contém uma implementação lenta ad hoc, especificada informalmente, cheia de bugs e com erros, de metade do Common Lisp.

O argumento de Greenspun foi (em parte) que muitos programas complexos têm intérpretes embutidos. Em vez de transformar um intérprete em um idioma, ele sugeriu que faria mais sentido usar um idioma como o Lisp, que já possui um intérprete (ou compilador) embutido.

Na época, eu trabalhava em um aplicativo bastante grande que executava cálculos definidos pelo usuário usando um intérprete personalizado para um idioma personalizado. Decidi tentar reescrever seu núcleo no Lisp como um experimento em larga escala.

Demorou cerca de seis semanas. O código original era de ~ 100.000 linhas de Delphi (uma variante de Pascal). No Lisp isso foi reduzido para ~ 10.000 linhas. Ainda mais surpreendente, porém, foi o fato de o mecanismo Lisp ser 3-6 vezes mais rápido. E tenha em mente que este foi o trabalho de um neófito Lisp! Toda essa experiência foi muito reveladora para mim; pela primeira vez, vi a possibilidade de combinar desempenho e expressividade em um único idioma.

Algum tempo depois, quando comecei a trabalhar em um projeto baseado na Web, testei vários idiomas. Incluí Lisp e Scheme na mistura. No final, selecionei uma implementação Scheme-- Chez Scheme . Fiquei muito feliz com os resultados.

O projeto baseado na Web é um "mecanismo de seleção" de alto desempenho . Usamos o Scheme de várias maneiras diferentes, desde o processamento de dados até a consulta de dados até a geração de páginas. Em muitos pontos, na verdade começamos com um idioma diferente, mas acabamos migrando para o Scheme por razões que descreverei brevemente abaixo.

Agora eu posso responder sua pergunta (pelo menos em parte).

Durante a audição, analisamos várias implementações de Lisp e Scheme. No lado do Lisp, vimos (acredito) Allegro CL, CMUCL, SBCL e LispWorks. No lado do esquema, vimos (acredito) Bigloo, Frango, Chez, Gambit. (A seleção de idioma foi feita há muito tempo; é por isso que estou um pouco enevoado. Posso desenterrar algumas notas, se for importante.)

Logo de cara estávamos procurando a) threads nativas eb) suporte para Linux, Mac e Windows. Essas duas condições combinadas derrubaram todo mundo, exceto (acho) Allegro e Chez - então, para continuar a avaliação, tivemos que afrouxar o requisito de multiencadeamento.

Montamos um conjunto de pequenos programas e os usamos para avaliação e teste. Isso revelou uma série de questões. Por exemplo: algumas implementações tinham defeitos que impediam a execução de alguns testes; algumas implementações não puderam compilar código em tempo de execução; algumas implementações não conseguiram integrar facilmente o código compilado em tempo de execução ao código pré-compilado; algumas implementações tinham coletores de lixo claramente melhores (ou claramente piores) que as outras; etc.

Para nossas necessidades, apenas as três implementações comerciais - Allegro, Chez e Lispworks - passaram nos nossos testes primários. Dos três, apenas Chez passou em todos os testes com cores voadoras. Na época, acho que o Lispworks não tinha threads nativos em nenhuma plataforma (acho que agora) e acho que o Allegro só tinha threads nativos em algumas plataformas. Além disso, a Allegro tinha uma taxa de licenciamento em tempo de execução "que nos chamava", da qual eu não gostava muito. Acredito que o Lispworks não tinha taxa de tempo de execução e o Chez tinha um arranjo simples (e muito razoável) (e só funcionava se você usasse o compilador em tempo de execução).

Tendo produzido partes de código um tanto significativas no Lisp e no Scheme, aqui estão alguns pontos de comparação e contraste:

  • Os ambientes Lisp são muito mais maduros. Você ganha muito mais dinheiro. (Dito isso, mais código também equivale a mais bugs.)

  • Os ambientes Lisp são muito mais difíceis de aprender. Você precisa de muito mais tempo para se tornar proficiente; O Lisp comum é uma linguagem enorme - e isso é antes de você chegar às bibliotecas que as implementações comerciais adicionam sobre ela. (Dito isso, o caso de sintaxe de Scheme é muito mais sutil e complicado do que qualquer coisa no Lisp.)

  • Os ambientes Lisp podem ser um pouco mais difíceis de produzir binários. Você precisa "agitar" sua imagem para remover bits desnecessários e, se você não exercitar seu programa corretamente durante esse processo, poderá acabar com erros de tempo de execução posteriormente. . Por outro lado, com o Chez, compilamos um arquivo de nível superior que inclui todos os outros arquivos necessários e pronto.

Eu disse antes que acabamos usando o Scheme em vários lugares que não pretendíamos originalmente. Por quê? Eu posso pensar em três razões em cima da minha cabeça.

Primeiro, aprendemos a confiar no Chez (e seu desenvolvedor, Cadence). Pedimos muito à ferramenta e ela foi entregue de forma consistente. Por exemplo, o Chez tem historicamente um número trivialmente pequeno de defeitos e seu gerenciador de memória tem sido muito, muito bom.

Segundo, aprendemos a amar o desempenho que recebemos do Chez. Estávamos usando algo que parecia uma linguagem de script - e estávamos obtendo velocidade do código nativo a partir dela. Para algumas coisas que não importavam - mas nunca doía, e às vezes ajudava muito.

Terceiro, aprendemos a amar a abstração que o Esquema poderia proporcionar. A propósito, não me refiro apenas a macros; Quero dizer coisas como fechamentos, lambdas, chamadas finais, etc. Quando você começa a pensar nesses termos, outras línguas parecem bastante limitadas em comparação.

Scheme é perfeito? Não; é uma troca. Primeiro, ele permite que desenvolvedores individuais sejam mais eficazes - mas é mais difícil para os desenvolvedores grunhir o código um do outro, porque as indicações que a maioria dos idiomas possui (por exemplo, para loops) estão ausentes no Scheme (por exemplo, existem milhões de maneiras de fazer um loop for). Segundo, há um grupo muito menor de desenvolvedores para conversar, contratar e emprestar, etc.

Para resumir, acho que diria: Lisp e Scheme oferecem alguns recursos que não estão amplamente disponíveis em nenhum outro lugar. Essa capacidade é uma troca, portanto é melhor que ela faça sentido no seu caso particular. No nosso caso, os fatores determinantes entre escolher o Lisp ou o Scheme tinham mais a ver com recursos muito fundamentais (suporte da plataforma, threads da plataforma, compilação em tempo de execução, licenciamento em tempo de execução) do que com os recursos de idioma ou biblioteca. Novamente, no nosso caso, isso também foi uma troca: com o Chez, obtivemos os principais recursos que queríamos, mas perdemos as extensas bibliotecas que os ambientes comerciais do Lisp tinham.

Além disso, apenas para reiterar: analisamos os vários Lisps e Schemes há muito tempo; todos eles evoluíram e melhoraram desde então.


1
Uau, isso deve ter sido algum código Delphi realmente horrível, se de alguma forma conseguiu executar 3-6x mais lento que uma implementação Lisp! :(
Mason Wheeler

2
+1: A coisa mais interessante sobre este post é o fato de você ter mudado de Lisp para Scheme após concluir um grande projeto no Lisp. (Ou talvez eu tenha acabado de ser escondido em comp.lang.lisp muito longo.)
Larry Coleman

25
"Uau, isso deve ter sido um código Delphi realmente horrível, se de alguma forma conseguiu executar 3-6x mais lento que uma implementação do Lisp!" Certo, contarei isso como meu fracasso por não explicar melhor. A implementação do Lisp foi capaz de transformar expressões do usuário em expressões do Lisp - um processo trivialmente fácil - e depois compilar as expressões do Lisp no código nativo (com otimização total). Esse é o significado da Décima Regra de Greenspun.
Michael Lenaghan 29/03

1
Resposta fantástica! Eu escolherei, pelo menos até que uma melhor apareça :) Uma pergunta: você diz que tomou a decisão de usar o Chez Scheme com base no estado do campo "há muito tempo". Você poderia especificar um ano?
SuperElectric 31/03

11
Esse ponto, que a implementação do LISP é livre para compilar algo até o código da máquina, em vez de depender de um intérprete, é sutil e bastante útil. O livro "Let Over Lambda" ressalta que é exatamente por isso que o pacote regexp portátil Common LISP, que clona a sintaxe do regexp PERL, supera o PERL por um fator significativo. PERL, ao lado, tem um intérprete regexp. O pacote Common LISP compila os regexps no código.
John R. Strohm

37

Normalmente, não gosto de colar um link como resposta, mas escrevi um artigo de blog sobre isso. Não é exaustivo, mas obtém alguns dos principais pontos.

http://symbo1ics.com/blog/?p=729

Edit : Aqui estão os principais pontos:

  1. EXISTÊNCIA : Ambos os lisps vieram atrás de um monte de outros lisps. O esquema seguiu a rota axiomática mínima. CL tomou a rota barroca.
  2. CASO : Normalmente, o esquema diferencia maiúsculas de minúsculas. CL não é (embora possa ser). Às vezes isso é esquecido, mas sua praticidade é debatida (por mim).
  3. NOMES : Os nomes dos símbolos no CL são muitas vezes estranhos e confusos. TERPRI, PROGNetc. O esquema geralmente possui nomes muito sensíveis. Isso é algo perdido no CL.
  4. FUNÇÕES : CL tem um espaço para nome de função separado. Isso não é esquecido no esquema. Ter um único espaço para nome geralmente permite uma programação funcional muito limpa, que geralmente é difícil ou incômoda no CL. Mas tem um custo - às vezes você precisa ofuscar nomes como " list" para " lst" em Esquema.
  5. MACROS : Sinto muita falta das macros sujas de baixo nível no Scheme. Sim, syntax-rulesestá tudo bem e elegante até que você queira realmente fazer algumas coisas. Por outro lado, às vezes, as macros higiênicas são perdidas no CL. Não ter uma maneira padrão de fazê-las significa reinventar a roda.
  6. PORTABILIDADE : Geralmente, o CL é mais portátil, apesar de os dois idiomas serem padronizados. O CL é maior e, portanto, há mais recursos padrão a serem usados ​​sem bibliotecas externas. Isso também significa que coisas mais dependentes da implementação podem ser feitas de maneira portável. Além disso, o Scheme sofre de ter um trilhão de implementações, a maioria das quais é um tanto incompatível. Isso torna o CL muito desejável.
  7. BIBLIOTECAS : Muito relacionado ao meu último ponto. O esquema possui SRFIs, mas não é universalmente reconhecido. Não há uma maneira portátil de trabalhar com bibliotecas. CL, por outro lado, tem maneiras. E o Quicklisp é um presente de deus (Xach) - uma espécie de repositório de bibliotecas para uso.
  8. IMPLEMENTAÇÕES : O esquema sofre com tantas implementações. Não existe uma implementação canônica real. O CL, por outro lado, possui algumas implementações de alto desempenho ou uso específico muito agradáveis ​​(alto desempenho: SBCL, comercial: Allegro, incorporado: ECL, portátil: CLISP, Java: ABCL, ...).

Embora eu tenha falado apenas na primeira pessoa um pouco acima, deve ficar claro o que sinto falta e o que não sinto.

[Peço desculpas se estas são muito gerais. Parece que você pode querer detalhes muito mais específicos. Existem alguns detalhes na postagem.]


o que dizer de um (muito) breve resumo provocação ^^?
Dave O.

2
Por favor, inline os destaques. As respostas devem ser autônomas.

1
@Dave O. e @ Thorbjørn Ravn Andersen: Adicionado um resumo conforme solicitado. Obrigado.
Quadrescence 21/03

2
"A rota barroca"! Que excelente maneira de colocá-lo.
Mark C

O Lisp comum diferencia maiúsculas de minúsculas, mas converte sua entrada em maiúsculas antes de avaliá-la. Você pode obter letras minúsculas nos símbolos, citando-os. A questão do nome é que Scheme se livrou dos nomes antigos ruins e CL não.
David Thornley

25

Recentemente, iniciei um projeto doméstico usando uma biblioteca que possui uma versão C e uma versão Java. Queria usar o Lisp para o projeto e passei um mês vacilando entre o uso do Common Lisp, Scheme ou Clojure. Eu tenho alguma experiência com todos os três, mas apenas projetos de brinquedos. Vou contar um pouco sobre a minha experiência com cada um deles antes de dizer qual acabei escolhendo.

O PLT Racket possui um bom IDE que não apenas permite avaliar expressões do editor, mas também digita colchetes em vez de parênteses, alternando-os novamente para parênteses, quando apropriado. O Racket também possui um grande conjunto de bibliotecas com a instalação e ainda mais disponíveis para download. O depurador visual também é útil.

Minha implementação Common Lisp (SBCL) não possui um IDE, mas é comum nas implementações de código-fonte aberto CL usar Emacs e SLIME. Essa combinação pode ser muito eficiente. Juntamente com a capacidade de avaliar expressões à medida que você as digita no arquivo de origem, há também um REPL que possui todos os comandos de edição do emacs disponíveis, para que a cópia do código possa ser executada de maneira eficiente nos dois sentidos. Mesmo objetos exibidos no buffer REPL podem ser copiados e colados. Alt+(e Alt+)são eficientes para lidar com parênteses e indentações correspondentes.

Todos os recursos acima do Emacs também estão disponíveis para o Clojure. Minha experiência de edição com o Clojure é semelhante à do Lisp. A interoperabilidade Java funcionou bem e eu gostaria de fazer um projeto Clojure assim que amadurecer.

Consegui acessar a biblioteca usando todos os três (Common Lisp, Racket e Clojure), mas acabei escolhendo o Common Lisp para o projeto. O fator decisivo foi que o FFI era muito mais fácil de usar no Common Lisp. O CFFI possui um manual muito bom com código de exemplo e explicações detalhadas de cada método. Consegui agrupar 20 funções C em uma tarde e não precisei tocar no código desde então.

O outro fator é que eu estou mais familiarizado com o Common Lisp do que com o Clojure ou o R6RS Scheme. Eu li a maioria dos livros de Practical Common Lisp e Graham, e me sinto confortável com o Hyperspec. Ainda não é um código "lispy", mas tenho certeza de que isso mudará à medida que eu ganhar mais experiência.


Obrigado pelo detalhe! Entendi corretamente que você achava que o FFI da SBCL era mais fácil de usar do que o Clojure? Nesse caso, ficaria surpreso com isso, já que você pode chamar métodos Java diretamente do Clojure sem precisar envolvê-los. (Ou você também precisa chamar código nativo?)
SuperElectric

6
@SuperElectric: Chamar métodos Java "internos" do Clojure é trivial; chamando métodos Java que estão em uma biblioteca baixada: nem tanto. Eu realmente gastei mais tempo adquirindo o caminho de classe e importando as linhas do que demorei para que meu primeiro método C funcionasse na SBCL com CFFI. Mas como eu não sou especialista em Java, sua milhagem pode variar.
Larry Coleman

21

Eu programa em CL e Racket.

Estou desenvolvendo um site agora no Common Lisp e escrevi um conjunto de programas internos para meu empregador anterior na Racket.

Para o código interno, escolhi o Racket (então conhecido como PLT Scheme) porque o empregador era uma loja do Windows e não conseguia que eles pagassem pelo LispWorks. A única boa implementação de CL de código-fonte aberto para Windows foi (e ainda é) o CCL, que requer suporte SSE no processador. O empregador, por ser barato, estava usando o hardware da Idade da Pedra. Mesmo se o empregador tivesse hardware decente, a única biblioteca de conseqüências da GUI no Common Lisp é o McCLIM, que funciona apenas no Unix. O Racket tem uma boa biblioteca de GUI que funciona tanto no Unix quanto no Windows, o que foi fundamental para o sucesso do meu projeto.

Passei mais de um ano suportando o editor primitivo do DrRacket. O EMACS não conseguiu transformar a versão da GUI do Racket, então conhecida como MrEd, em um cisco inferior no Windows. Eu tive que fazer sem poder avaliar a expressão no cursor com um único toque de tecla. Em vez disso, tive que selecionar manualmente a expressão S, copiá-la, clicar na janela REPL (porque não há pressionamento de tecla para alternar para ela) e colar a expressão S. Eu também tive que ficar sem um editor que pudesse me mostrar os argumentos esperados da função ou macro que eu estava usando. O DrRacket não substitui o SLIME.

O empregador estava usando um banco de dados proprietário com uma API XML complicada que exigia muitas informações aparentemente desnecessárias para poder responder à sua versão de uma consulta SELECT. Decidi usar o HTMLPrag para emitir XML para esta API e analisar as respostas. Funcionou muito bem.

Eu tive que aprender o sistema de macro "caso de sintaxe" complicado de Racket para escrever uma macro que me permitisse interagir com a API XML complicada demais digitando formulários que pareciam SQL. Esta parte teria sido muito mais fácil se eu tivesse o DEFMACRO à minha disposição. No entanto, o resultado final ainda foi perfeito, apesar de ter sido necessário mais esforço para alcançar.

Além disso, eu tive que ficar sem a macro LOOP do Common Lisp. O Racket começou a fornecer uma alternativa somente depois que eu escrevi a maior parte do código, e a alternativa ainda é péssima em comparação com o LOOP (mesmo que a equipe de desenvolvimento do Racket insista que é melhor - eles estão simplesmente errados). Acabei escrevendo muitos formulários LET nomeados que usavam "car" e "cdr" para percorrer as listas.

Falando em carro e cdr, nada é mais frustrante do que a interpretação de Scheme de (car '()) como sendo um erro. Tirei proveito da distinção entre maiúsculas e minúsculas de Racket e implementei o CAR e o CDR, que possuem a semântica do Common Lisp. No entanto, a separação de '() e #f torna muito menos útil retornar' () como um valor padrão.

Também acabei reimplementando UNWIND-PROTECT e inventei meu próprio sistema de reinicialização para preencher a lacuna deixada por Racket. A comunidade Racket precisa aprender que as reinicializações são muito úteis e fáceis de implementar.

O formulário let-values ​​de Racket era excessivamente detalhado, então eu implementei MULTIPLE-VALUE-BIND. Isso foi absolutamente necessário, porque o Racket exige que você receba todos os valores gerados, independentemente de você usá-los ou não.

Mais tarde, tentei escrever um cliente da API XML do eBay no Common Lisp, apenas para descobrir que ele não possui nada como HTMLPrag. HTMLPrag é muito útil. Acabei fazendo esse projeto no Racket. Eu experimentei as instalações de programação alfabetizada de Racket, apenas para descobrir que sou o único programador na Terra que acha mais difícil editar código alfabético escrito corretamente do que o código comum, ou código alfabético incorreto de "comentários excessivos".

Meu novo projeto está sendo realizado no Common Lisp, que foi a escolha certa, porque a comunidade Racket simplesmente não acredita em paralelismo, essencial para este projeto. A única coisa que pensei ter perdido de Racket foram as continuações. No entanto, consegui fazer o que precisava usando reinicializações e, em retrospecto, provavelmente poderia ter feito isso com um fechamento simples.


2
Eu ainda não tentei, mas já vi posts de pessoas que usam o programa de raquete de linha de comando com o Emacs. Por exemplo: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman

5
Com toda a justiça, parece que você veio ao Scheme querendo escrever CL em vez de tentar abordar as coisas de um PDV idiomático do esquema. Por exemplo, o esquema não incentiva a recorrência ao invés de usar loops?
Sled

O @ArtB Scheme não apenas incentiva a recursão, é necessária , portanto, é claro que o projeto mencionado acima usou muita recursão. E isso serviu apenas para adicionar repetição (você precisa incluir uma cópia da chamada recursiva em todas as ramificações de um condformulário, por exemplo) e bugs (eu escrevi o teste de finalização do loop corretamente dessa vez?) Ainda hoje, tenho a impressão esse Racket é destinado principalmente a estudantes e não a programadores profissionais. Toda vez que ouço alguém além de mim usá-lo, eles usam a sub-linguagem "Aluno Iniciante" e é para uma aula.
Jogue fora a conta

Se você está repetindo código entre CONDs, está dizendo que precisa apenas de outra função?
trenó

@ArtB Uma função para chamar a função loop com argumentos diferentes? Isso seria meio inútil. Você vê esse tipo de repetição no código de esquema de qualquer pessoa. Existem até exemplos no código-fonte do próprio Racket.
Jogue fora a conta

5

O esquema foi projetado com uma compilação separada em mente. Como conseqüência, o poder de suas macros costuma ser severamente limitado, mesmo com as extensões que permitem um defmacro no estilo Common Lisp, em vez de um sistema macro higiênico limitador e pobre. Nem sempre é possível definir uma macro que defina outra macro, destinada ao uso imediato em uma próxima linha de código. E essa possibilidade é essencial para a implementação de compiladores eDSL eficientes.

Desnecessário mencionar que implementações de esquema com apenas macros higiênicas R5RS são pouco úteis para mim, pois meu estilo de metaprogramação não pode ser adequadamente traduzido em higiene.

Felizmente, existem implementações de esquema (por exemplo, raquete) que não têm essa limitação.


1
Olá, comecei a molhar os pés com o Scheme recentemente usando o Racket. Você se importaria em fornecer um exemplo rápido do uso de macros não higiênicas no Racket? O tipo de macros disponíveis parece ser um dos pontos mais debatidos entre CL e Scheme.
orange80

@ orange80, a única abordagem é usar docs.racket-lang.org/mzlib/mzlib_defmacro.html E, é claro, no modo R6RS, existe uma maneira menos restritiva.
SK-logic

@ SK-logic, o que você está fazendo com macros tão anti-genéticas?
Trenó

1
@ArtB, estou implementando eDSLs como funções de compilador que podem fazer bastante com o AST de origem. A higiene é um incômodo total dentro dessa abordagem. Você pode dar uma olhada em como funciona: github.com/combinatorylogic/mbase
SK-logic
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.