его элегантность снова сияет - Спасибо @Sylwester!

инарной книге Эди Вейц, для питониковjoinэта функция предлагается:

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

Тем не менее, как-то я думал, должен быть способ выразитьjoin по-другому, может быть, используяformatвозможности ...

В книге Сейбела, (в главе оformat) мы находим соединение строк в списке в одну строку с разделителем", " по:

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

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

Который является питоническим соединением и который очень лаконичен;~^ директива делает это", " добавляется только до последнего элемента и не добавляется, когда ни один элемент не следует.

Тем не менее, здесь, разделитель строки", " является частью директивы формата.

Сложный случай, например,(defvar sep #\Tab), Если представление сеп"#\Tab" буквально может быть помещен как разделитель в середине этой директивы формата, что приводит к:

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

Мы бы достигли цели.

Очевидно, нужно использовать макрос для генерации директивы формата ... Я пробовал такие вещи, как(princ-to-string sep) но это дает"#\\Tab" и нет"#\Tab".

Например.

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

Но при попытке:

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

Эти результаты, конечно, не желательны:"a#\\Tabb#\\Tabc", поскольку

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

Но я не вижу, как сделать этот шаг к желаемому макросу ... Кто-нибудь просветил насчет этого?

Вид метапрограммирования на проблему метапрограммирования ...

Хорошо, теперь я вижу, что @Rainer Joswig уже опубликовал вКакой канонический способ объединения строк в списке?

решение этой проблемы. Однако, если бы был способ, представлять"#\\Tab" как"#\Tab"можно прийти к более компактному определению. Но каким-то образом читатель Lisp кажется в строке всегда распознать"\Tab" как одно письмо. Можно ли написать функцию для этого?

замечание

В R специально для метапрограммирования существуют такие функции, какas.name("myvar") которые генерируют символmyvar из строки "myvar". и выражения какdeparse(substitute(x)) который принимает символx и создает из него буквальную строку"x", Deparse шаги назад выполнениеprint() команды, в результате чего экранирование специальных символов.deparse(deparse(substitute(x))) например, генерировать"\"x\"" - Покаparse(text = ... ) вокруг этого выражения сделало бы из него"x" очередной разparse(text = deparse(deparse(substitute(x)))), Как такие вещи могут быть достигнуты в Common-LISP? например(a-special-function #\Tab) в результате (буквально):"#\Tab" как строка?

эпилог

Спасибо @Sylwester !! Он решил это без макроса. И очень элегантно!

Ответы на вопрос(1)

Ваш ответ на вопрос