Nicer pythonic `join` en common-lisp

En el libro de cocina cl de Edi Weitz, para el pitónjoin, se sugiere esta función:

(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))))

Sin embargo, de alguna manera estaba pensando, debe haber una manera de expresarjoin de otra manera, tal vez usandoformatas capacidades de @ ...

n el libro de Seibel, (en el capítulo sobreformat) encontramos unir cadenas en una lista a una sola cadena con el separador", " por:

(defvar l '("a" "b" "c"))

(format nil "~{~A~^, ~}" l)
;; "a, b, c"

Que es una unión pitónica y que es muy conciso; el~^a directiva @ hace que", " se agrega solo hasta justo antes del último elemento y no se agrega cuando ningún elemento lo sigue.

Sin embargo, aquí, la cadena de separación", " es parte de la directiva de formato.

Un caso complicado es, p. @(defvar sep #\Tab). Si la representación de sep"#\Tab" literalmente se puede colocar como un separador en medio de esta directiva de formato, lo que resulta en:

(format nil "~{~A~^#\Tab~}" l)

Hubiéramos alcanzado la meta.

Obviamente, uno tiene que usar una macro para generar la directiva de formato ... Intenté cosas como(princ-to-string sep) pero esto da"#\\Tab" y no"#\Tab".

P.ej

(defmacro join (sep l)
  `(format nil ,(format nil "~{~A~}" `("\~\{\~A\~\^" ,(write-to-string sep) "\~\}")) l))

Pero al intentar:

(join #\Tab '("a" "b" "c"))

Este resultado, por supuesto, no es deseado:"a#\\Tabb#\\Tabc", ya qu

(macroexpand-1 '(join #\Tab '("a" "b" "c")))
;; results in:
(FORMAT NIL "~{~A~^#\\Tab~}" L)
;; instead of:
(FORMAT NIL "~{~A~^#\Tab~}" L)

Pero no veo cómo lograr este paso hacia la macro deseada ... ¿Alguien tiene algo de esclarecedor sobre esto?

Tipo de metaprogramación en un problema de metaprogramación ...

ien, ahora veo que @Rainer Joswig ya ha publicado en ¿Cuál es la forma canónica de unir cadenas en una lista?

una solución a este problema. Sin embargo, si hubiera una forma de representar"#\\Tab" como"#\Tab", uno podría llegar a una definición más compacta. Pero de alguna manera el lector Lisp parece estar siempre en una cadena para reconocer"\Tab" como una letra. ¿Es posible escribir una función para hacer eso?

Observació

In R, existen especialmente para metaprogramación, funciones comoas.name("myvar") que generan el símbolomyvar fuera de la cadena "myvar". y expresiones comodeparse(substitute(x)) que toma el símbolox y crea una cadena literal"x". Deparse retrocede la ejecución deprint() comandos, mediante los cuales se escapan los símbolos especiales. @deparse(deparse(substitute(x))) p. ej. generar"\"x\"" - Mientrasparse(text = ... ) alrededor de esta expresión lo haría"x" otra vezparse(text = deparse(deparse(substitute(x)))). ¿Cómo se pueden lograr tales cosas en el lisp común? p.ej(a-special-function #\Tab) resultante en (literal):"#\Tab" como una cadena?

Epílog

Gracias @Sylwester !! Lo resolvió sin macro. ¡Y muy elegantemente!

Respuestas a la pregunta(1)

Su respuesta a la pregunta