Вопрос по list – Common Lisp - выравнивание списка, который может содержать символы

0

Это № 7 из99 проблем с Лиспом: преобразовать список, возможно, держа списки в виде элементов в «плоский»; список путем замены каждого списка его элементами (рекурсивно). Я пробовал несколько решений, например, от #2680864 или жеотсюда, Все они работают, но я сталкиваюсь с проблемой, если сглаживаю список, содержащий элемент в кавычках. Например.:

> '(a 'b c)
(A 'B C)

> '(a (quote b) c)
(A 'B C)

> (flatten '(a 'b c))
(A QUOTE B C)

В последнем случае я хотел бы получить:

(A 'B C)

Кажется, что внутреннее представление & apos; мешает для этой задачи! SBCL, CLISP, ECL, ... все они ведут себя одинаково.

Проблема, с которой вы столкнулись, связана с тем, что символ кавычки (& quot;) преобразуется в (кавычка ...), когда LISP читает выражение. Чтобы было легче прочитать вывод, происходит соответствующее преобразование, когда LISP печатает ваш список. Следовательно, нет никакого способа различить их, когда LISP читает их как список. Filip

Ваш Ответ

1   ответ
2

ам это процитировать?

(a b c) это список из трех символов. Зачем вы цитируете элементы в списке? как в(a 'b c)? Зачем? Какова будет цель цитаты?

В Common Lisp' это readmacro, который расширяется'a в(QUOTE A), Так как это обычный список, типичная операция выравнивания будет собирать символыQUOTE а такжеA в плоский список. Это связано с тем, что функция flatten обычно проверяет, является ли что-то атомом или нет. Если вы этого не хотите, ваша функция выравнивания должна проверить, является ли что-то атомом или двухэлементным списком сQUOTE как его первый символ.

Но, как я уже сказал выше, по умолчанию используется только выравнивание символов, поскольку символы в кавычках обычно бесполезны внутри списка. В противном случае вам нужно расширить функцию выравнивания.

Например:

(defun flatten (l &key (test #'atom))
  (cond ((null l) nil)
        ((funcall test l) (list l))
        (t (loop for a in l nconc (flatten a :test test)))))


CL-USER > (flatten '(a (('b) c) ('d) )
                   :test (lambda (item)
                           (or (atom item)
                               (and (eq (first item) 'quote)
                                    (null (cddr item))))))

(A (QUOTE B) C (QUOTE D))
Error: User Rate Limit Exceeded
(defun flatten (l) (cond ((null l) nil) ((atom l) (list l)) ((equal l (list 'QUOTE (second l))) (cdr l)) (t (loop for a in l appending (flatten a)))))Error: User Rate Limit Exceeded(A B C)Error: User Rate Limit Exceeded(A 'B C)Error: User Rate Limit Exceeded(flatten '(A 'B C))Error: User Rate Limit Exceeded Antonio Bonifati 'Farmboy'

Похожие вопросы