Mais agradável python `join` no common-lisp
No livro de receitas de Edi Weitz, para o pítônicojoin
, esta função é sugerida:
(defun join (separator list)
(with-output-to-string (out)
(loop for (element . more) on list
do (princ element out)
when more
do (princ separator out))))
No entanto, de alguma forma, eu estava pensando, deve haver uma maneira de expressarjoin
de outra maneira, talvez usandoformat
capacidades de ...
No livro de Seibel (no capítulo sobreformat
) encontramos a junção de strings em uma lista a uma única string com o separador", "
por:
(defvar l '("a" "b" "c"))
(format nil "~{~A~^, ~}" l)
;; "a, b, c"
Qual é uma junção pitônica e que é muito concisa; a~^
directiva faz com que", "
é adicionado apenas até pouco antes do último elemento e não adicionado quando nenhum elemento está seguindo.
No entanto, aqui, a sequência separadora", "
faz parte da diretiva de formato.
Um caso complicado é p.(defvar sep #\Tab)
. Se a representação de setembro"#\Tab"
literalmente pode ser colocado como um separador no meio desta diretiva de formato, resultando em:
(format nil "~{~A~^#\Tab~}" l)
Teríamos atingido a meta.
Obviamente, é preciso usar uma macro para gerar a diretiva de formato ... Tentei coisas como(princ-to-string sep)
mas isso dá"#\\Tab"
e não"#\Tab"
.
Por exemplo.
(defmacro join (sep l)
`(format nil ,(format nil "~{~A~}" `("\~\{\~A\~\^" ,(write-to-string sep) "\~\}")) l))
Mas ao tentar:
(join #\Tab '("a" "b" "c"))
Naturalmente, esses resultados não são desejados:"a#\\Tabb#\\Tabc"
, Desde a
(macroexpand-1 '(join #\Tab '("a" "b" "c")))
;; results in:
(FORMAT NIL "~{~A~^#\\Tab~}" L)
;; instead of:
(FORMAT NIL "~{~A~^#\Tab~}" L)
Mas não vejo como conseguir essa etapa para a macro desejada ... Alguém tem uma idéia sobre isso?
Tipo de metaprogramação no problema de metaprogramação ...
Ok, agora vejo que @Rainer Joswig já postou emQual é a maneira canônica de juntar strings em uma lista?
uma solução para esse problema. No entanto, se houvesse uma maneira de representar"#\\Tab"
Como"#\Tab"
, pode-se chegar a uma definição mais compacta. Mas, de alguma forma, o leitor Lisp parece sempre reconhecer"\Tab"
como uma letra. É possível escrever uma função para fazer isso?
Observação
Em R, existem especialmente para metaprogramação, funções comoas.name("myvar")
que geram o símbolomyvar
fora da cadeia "myvar". e expressões comodeparse(substitute(x))
que leva o símbolox
e cria a partir dele uma string literal"x"
. Separar etapas para trás a execução deprint()
comandos, através dos quais se escapam símbolos especiaisdeparse(deparse(substitute(x)))
por exemplo gerar"\"x\""
- Enquantoparse(text = ... )
em torno desta expressão faria com que"x"
novamenteparse(text = deparse(deparse(substitute(x))))
. Como essas coisas poderiam ser alcançadas em linguagem comum? por exemplo.(a-special-function #\Tab)
resultando em (literal):"#\Tab"
como uma corda?
Epílogo
Obrigado @Sylwester !! Ele resolveu sem macro. E muito elegantemente!