Até que ponto pode macros LISP ir?

votos
43

Eu li um monte de que LISP pode redefinir sintaxe on the fly, presumivelmente com macros. Estou curioso o quão longe que isso realmente ir? você pode redefinir a estrutura da linguagem tanto que limítrofe torna-se um compilador para uma outra língua? Por exemplo, você poderia mudar a natureza funcional de LISP em um objeto orientado sintaxe e semântica mais, talvez dizem ter sintaxe mais perto de algo como Ruby?

Especialmente, é possível livrar-se do inferno parêntese usando macros? Eu aprendi o suficiente LISP (Emacs-) para personalizar Emacs com meus próprios micro-características, mas estou muito curioso como macros agora pode ir para personalizar o idioma.

Publicado 05/08/2008 em 08:32
fonte usuário
Em outras línguas...                            


14 respostas

votos
33

Essa é uma pergunta muito boa.

Eu acho que é sutil, mas definitivamente responde:

Macros não está preso em S-expressões. Veja a macro LOOP para uma linguagem muito complexa escrito usando palavras-chave (símbolos). Então, enquanto você pode começar e terminar o ciclo com parênteses, dentro dele tem sua própria sintaxe.

Exemplo:

(loop for x from 0 below 100
      when (even x)
      collect x)

Dito isto, macros mais simples é só usar s-expressões. E você estaria "preso" usá-los.

Mas s-expressões, como Sérgio respondeu, começar a se sentir bem. A sintaxe fica fora do caminho e você começar a codificar na árvore de sintaxe.

Quanto macros leitor, sim, você pode conseguir escrever algo como isto:

#R{
      ruby.code.goes.here
  }

Mas você precisa escrever seu próprio analisador de sintaxe Ruby.

Você também pode imitar alguns dos Rubi constrói, como blocos, com macros que compilam as construções Lisp existentes.

#B(some lisp (code goes here))

se traduziria em

(lambda () (some lisp (code goes here)))

Veja esta página para saber como fazê-lo.

Respondeu 15/09/2008 em 16:07
fonte usuário

votos
20

Sim, você pode redefinir a sintaxe para que Lisp torna-se um compilador. Você pode fazer isso usando "Leitor Macros", que são diferentes do normal "Compiler Macros" que você provavelmente está pensando.

Lisp Comum tem a facilidade built-in para definir nova sintaxe para o leitor e leitor macros para processar essa sintaxe. Este processamento é feito em tempo de ler (que vem antes de compilar ou tempo eval). Para saber mais sobre a definição de macros leitor em Common Lisp, consulte o Lisp HyperSpec comum - você vai querer ler Ch. 2, "Sintaxe" e Ch. 23, "Reader" . (Eu acredito Esquema tem a mesma facilidade, mas eu não sou tão familiarizado com ele - veja as fontes Esquema para a linguagem de programação Arc ).

Como um exemplo simples, vamos supor que você quer Lisp usar chaves em vez de parênteses. Isso requer algo como as seguintes definições do leitor:

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

Você está dizendo Lisp que a {é como uma (e que o} é como a). Em seguida, você criar uma função ( lcurly-brace-reader) que o leitor irá chamar sempre que vê um {, e você usar set-macro-characterpara atribuir essa função à {. Então você diz Lisp que (e) são como [e] (isto é, não significativa de sintaxe).

Outras coisas que você pode fazer incluem, por exemplo, a criação de uma nova sintaxe da cadeia ou utilizando [e] para incluir a notação em-fix e processá-lo em S-expressões.

Você também pode ir muito além disso, a redefinição de toda a sintaxe com seus próprios personagens de macro que irá desencadear ações no leitor, assim que o céu é o limite. Esta é apenas uma das razões pelas quais Paul Graham e outros continuam dizendo que Lisp é uma boa linguagem para escrever um compilador.

Respondeu 16/09/2008 em 20:28
fonte usuário

votos
16

Eu não sou um especialista em Lisp, diabos eu não sou mesmo um programador Lisp, mas depois de um pouco de experimentação com a linguagem, cheguei à conclusão de que depois de um tempo o parêntese começar a se tornar 'invisível' e você começa a ver o código como você quer que ele seja. Você começar a prestar mais atenção às construções sintáticas que você criar via s-exprs e macros, e menos com a forma lexical do texto de listas e parênteses.

Isto é especialmente verdadeiro se você tirar proveito de um bom editor que ajuda com o recuo e coloração de sintaxe (tente definir o parêntese para uma cor muito semelhante ao fundo).

Você pode não ser capaz de substituir a linguagem completamente e obter a sintaxe 'Ruby', mas você não precisa dele. Graças à flexibilidade linguagem você pode acabar tendo um dialeto que se sente como você está seguindo o 'estilo de Rubi da programação', se quiser, seja lá o que isso significaria para você.

Eu sei que isto é apenas uma observação empírica, mas eu acho que eu tinha um daqueles momentos de esclarecimento Lisp quando eu percebi isso.

Respondeu 26/08/2008 em 10:49
fonte usuário

votos
15

Uma e outra vez, os recém-chegados Lisp quer "se livrar de tudo o parêntese." Tem a duração de algumas semanas. No projeto para construir uma séria sintaxe de programação de propósito geral no topo do analisador S-expressão usual nunca chega a lugar nenhum, porque os programadores invariavelmente acabam preferindo o que atualmente percebem como "inferno parênteses." Demora um pouco para se acostumar, mas não muito! Uma vez que você se acostumar com isso, e você pode realmente apreciar a plasticidade da sintaxe padrão, indo de volta para línguas onde há apenas uma maneira de expressar qualquer construção de programação particular é realmente ralar.

Dito isto, Lisp é um excelente substrato para a construção Domain Specific Languages. Tão bom quanto, se não melhor do que, XML.

Boa sorte!

Respondeu 16/09/2008 em 20:29
fonte usuário

votos
12

A melhor explicação de macros Lisp que eu já vi é a

https://www.youtube.com/watch?v=4NO83wZVT0A

a partir de cerca de 55 minutos. Este é um vídeo de uma palestra dada por Peter Seibel, o autor de "Practical Common Lisp", que é o melhor livro de Lisp que existe.

A motivação para macros Lisp geralmente é difícil de explicar, porque eles realmente entrar em seu próprio em situações que são demasiado longos para apresentar em um tutorial simples. Peter vem com um grande exemplo; você pode agarrá-lo completamente, e faz bom uso, adequado de macros Lisp.

Você perguntou: "você poderia mudar a natureza funcional de LISP em um objeto orientado sintaxe e semântica mais". A resposta é sim. Na verdade, Lisp originalmente não têm qualquer tipo de programação orientada a objetos em tudo, não é surpreendente, uma vez Lisp tem sido em torno desde muito antes de programação orientada a objetos! Mas quando soubemos pela primeira vez sobre OOP em 1978, fomos capazes de adicioná-lo à Lisp facilmente, utilizando, entre outras coisas, macros. Eventualmente, o Common Lisp Object System (CLOS) foi desenvolvido, um sistema de programação orientada a objeto muito poderoso que se encaixa elegantemente em Lisp. A coisa toda pode ser carregado como uma extensão - nada é built-in! É tudo feito com macros.

Lisp tem uma característica completamente diferente, chamado de "macros leitor", que pode ser usado para estender a sintaxe superfície da língua. Usando macros leitor, você pode fazer sublinguagens que têm sintaxe C-like ou Ruby-like. Eles transformar o texto em Lisp, internamente. Estes não são amplamente utilizados pela maioria dos programadores Lisp reais, principalmente porque é difícil de estender o ambiente de desenvolvimento interativo para compreender a nova sintaxe. Por exemplo, comandos de recuo Emacs seria confundido por uma nova sintaxe. Se você é enérgico, porém, Emacs é extensível também, e você poderia ensiná-lo sobre a sua nova sintaxe lexical.

Respondeu 05/10/2008 em 16:03
fonte usuário

votos
11

Macros regulares operar em listas de objetos. Mais vulgarmente, esses objectos são outras listas (árvores), formando assim e símbolos, mas podem ser outros objectos, tais como cordas, hashtables, objectos definidos pelo utilizador, etc. Essas estruturas são chamadas s-exps .

Então, quando você carrega um arquivo de origem, o compilador Lisp irá analisar o texto e produzir s-exps. Macros operar sobre estes. Isso funciona muito bem e é uma maneira maravilhosa de estender a linguagem dentro do espírito de s-exps.

Além disso, o processo de análise referido pode ser estendido através de "macros leitor" que permitem personalizar a forma como o compilador transforma texto em s-exps. Sugiro, porém, que você abraçar sintaxe de Lisp em vez de dobrá-la em outra coisa.

Você parece um pouco confuso quando você menciona a "natureza funcional" do Lisp e "sintaxe orientada a objeto" de Ruby. Eu não tenho certeza do que "sintaxe orientada a objeto" é suposto ser, mas Lisp é uma linguagem multi-paradigma e suporta programação orientada a objetos extremelly bem.

BTW, quando digo Lisp, quero dizer Common Lisp .

Eu sugiro que você colocar os seus preconceitos de distância e dar Lisp um movimento honesto .

Respondeu 26/08/2008 em 10:36
fonte usuário

votos
9

O que você está pedindo é um pouco como perguntar como se tornar um chocolatier especialista para que você pode remover todo esse material marrom infernal de seu bolo de chocolate favorito.

Respondeu 17/09/2008 em 13:14
fonte usuário

votos
9

Parêntese inferno? Não vejo mais parêntese em:

(function toto)

que em:

function(toto);

E em

(if tata (toto)
  (titi)
  (tutu))

não mais do que em:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

Vejo menos suportes e ';' Apesar.

Respondeu 16/09/2008 em 17:23
fonte usuário

votos
6

Sim, você pode mudar fundamentalmente a sintaxe, e até mesmo escapar "o inferno parênteses". Para isso você precisará definir uma nova sintaxe leitor. Olhe para macros leitor.

Eu suspeito, porém, que para alcançar o nível de conhecimento Lisp para programar essas macros que você vai precisar para mergulhar na língua de tal forma que você não vai mais considerar parenthese "inferno". Ou seja, o tempo que você sabe como evitá-los, você terá chegado a aceitá-los como uma coisa boa.

Respondeu 15/09/2008 em 13:07
fonte usuário

votos
2

veja este exemplo de como macros leitor pode estender o leitor lisp com tarefas complexas como a templates XML:

http://common-lisp.net/project/cl-quasi-quote/present-class.html

esta biblioteca do usuário compila as partes estáticas da XML em matrizes de bytes literal UTF-8 codificado em tempo de compilação que estão prontos para ser escrever-sequence'd na corrente de rede. e eles são utilizáveis em macros lisp normais, eles são ortogonais ... a colocação das influências caractere vírgula quais partes são constantes e que devem ser avaliadas em tempo de execução.

mais detalhes disponíveis em: http://common-lisp.net/project/cl-quasi-quote/

outro projeto que para extensões de sintaxe Common Lisp: http://common-lisp.net/project/cl-syntax-sugar/

Respondeu 17/09/2008 em 01:30
fonte usuário

votos
2

Se você quiser lisp para olhar como Ruby usar Ruby.

É possível usar Ruby (e Python) de uma forma muito lisp como que é uma das principais razões pelas quais eles ganharam aceitação tão rapidamente.

Respondeu 05/08/2008 em 08:40
fonte usuário

votos
1

Um dos usos de macros que fundiu minha mente era a verificação em tempo de compilação de pedidos SQL contra DB.

Uma vez que você percebe que tem a língua cheia na mão em tempo de compilação, ela abre novas perspectivas interessantes. O que também significa que você pode atirar no próprio pé em novas formas interessantes (como prestação de compilação não reprodutível, que pode muito facilmente se transformar em um pesadelo de depuração).

Respondeu 19/09/2008 em 11:43
fonte usuário

votos
1

É uma pergunta complicada. Desde lisp já é estruturalmente tão perto de uma árvore de análise a diferença entre um grande número de macros e implementar o seu próprio mini-linguagem em um gerador de analisador não é muito clara. Mas, exceto para os de abertura e fechamento parêntese, você poderia facilmente acabar com algo que parece em nada com lisp.

Respondeu 06/08/2008 em 13:14
fonte usuário

votos
1

@sparkes

Às vezes LISP é a escolha linguagem clara, ou seja, as extensões do Emacs. Eu tenho certeza que eu poderia usar Ruby para estender o Emacs, se eu quisesse, mas Emacs foi projetado para ser estendido com LISP, por isso parece fazer sentido usá-lo nessa situação.

Respondeu 05/08/2008 em 08:45
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more