Como quebrar e executar uma expressão s de lisp por outra expressão
Eu tentei quebrar uma expressão lisp por outra expressão lisp. Eu acho que uma macro deve fazer isso, mas eu não entendo o truque. Alguém pode me ajudar, quem sabe como fazer isso?
Meu objetivo real é escrever uma macro que envolva um lote dewith-open-file
xpressões em torno de algum código de macro-corp
(Eu quero escrever um script / programa, que abra um ou dois arquivos de entrada, processe-os linha por linha, mas também produz o resultado do processamento em vários arquivos de saída independentes diferentes. Por isso, eu adoraria ter owith-open-file
hamadas de macro empilhadas em torno do código que processa e grava nos arquivos de saída independentes - todos abertos para o código do corpo da macro
Desde owith-open-file
requer um símbolo (manipulador) para o fluxo de entrada ou saída e a variável de caminho para o arquivo de saída (ou entrada) e algumas informações adicionais (direção do arquivo etc.), desejo colocá-las em listas.
;; Output file-paths:
(defparameter *paths* '("~/out1.lisp" "~/out2.lisp" "~/out3.lisp"))
;; stream handlers (symbols for the output streams)
(defparameter *handlers* '(out1 out2 out3))
;; code which I would love to execute in the body
(print "something1" out1)
(print "something2" out2)
(print "something3" out3)
Como eu adoraria que a macro fosse chamada:
(with-open-files (*handlers* *paths* '(:direction :output :if-exists :append))
;; the third macro argument should be what should be passed to the
;; individual `with-open-file` calls
;; and it might be without `quote`-ing or with `quote`-ing
;; - is there by the way a good-practice for such cases? -
;; - is it recommended to have `quote`-ing? Or how would you do that? -
;; and then follows the code which should be in the macro body:
(print "something1" out1)
(print "something2" out2)
(print "something3" out3))
Para o que a chamada de macro deve expandir:
(with-open-file (out1 "~/out1.lisp" :direction :output :if-exists :append)
(with-open-file (out2 "~/out2.lisp" :direction :output :if-exists :append)
(with-open-file (out3 "~/out3.lisp" :direction :output :if-exists :append)
(print "something1" out1)
(print "something2" out2)
(print "something3" out3))))
Como um passo, pensei em fazer uma expressão s envolver outra expressão s.
inha primeira pergunta foi:Como quebrar uma expressão s por outra expressão s? Mas eu simplesmente não conseguia gerenciá-lo neste momento. Tudo o que eu pude fazer foi escrever uma função que apenas expele uma expressão não executada. Como escrever uma macro que faz o mesmo, mas também executa o código após expandi-lo dessa maneir
(defun wrap (s-expr-1 s-expr-2)
(append s-expr-1 (list s-expr-2)))
(wrap '(func1 arg1) '(func2 arg2))
;; => (FUNC1 ARG1 (FUNC2 ARG2))
(wrap '(with-open-files (out1 "~/out1.lisp" :direction :output :if-exists :append))
'(with-open-files (out2 "~/out2.lisp" :direction :output :if-exists :append)
(print "something1" out1)
(print "something2" out2)
(print "something3" out3)))
Que dá
(WITH-OPEN-FILES (OUT1 "~/out1.lisp" :DIRECTION :OUTPUT :IF-EXISTS :APPEND)
(WITH-OPEN-FILES (OUT2 "~/out2.lisp" :DIRECTION :OUTPUT :IF-EXISTS :APPEND)
(PRINT "something1" OUT1)
(PRINT "something2" OUT2)
(PRINT "something3" OUT3)))
Desta forma, aplicandowrap
funcionar sucessivamente, passando pelas listas de entrada, eu poderia criar o código talvez ...
No entanto, essas funções gerariam apenas código, mas não o executariam. E eu seria forçado no final a usar oeval
função para avaliar o código criado ... (Mas de alguma forma eu sei que isso não deve ser feito assim. E eu realmente não entendi como escrever macros que fazem essas coisas ... Na verdade, as macros estão lá para resolver exatamente esses problemas ...)
Com a execução, acabei de ter um grande problema. E como não se pode chamarfuncall
ouapply
em macros (em vez de nomes de funções) não vejo uma solução óbvia. Alguém teve experiência com esse tipo de situação?
E quando concluir a quebra de uma expressão s em uma macro por outra expressão s e seja avaliado, a próxima pergunta seria: como processar a lista para permitir que o código se expanda para o código desejado e depois seja avaliado? Apenas tentei horas e não fui long
Preciso da ajuda de alguém com experiência para escrever esse tipo de macros ...