Я пишу программу, которая берет список и заменяет все элементы (будь то атом, минус или список) на «X». Итак, если бы я оценивал свою функцию с помощью:

((A B) (C . D) E))

Это вернется

((X X) (X . X) X))

Однако при попытке оценить мою функцию я продолжаю получать ошибку «X не относится к ожидаемому типу LIST». Но я не понимаю почему. Я использую выпуск Allegro Common Lisp Express под Windows. Что я делаю не так?

(defun exify (lst)
  (exify-aux lst nil))

(defun exify-aux (lst acc)
  (if (null lst)
      acc
    (if (atom (car lst))
        (append 'x acc)
      (if (consp (car lst))
          (append (cons 'x 'x) acc)
        (if (listp (car lst))
            (append (exify-aux (car lst) nil) acc)
          (if (eq (car lst) nil)
              (append nil acc))))))

  (exify-aux (cdr lst) acc))
0
OrangeCalx01 4 Янв 2016 в 01:28

2 ответа

Лучший ответ

В вашем коде много мертвого кода, и в конечном итоге это бесконечный цикл.

(defun exify-aux (lst acc)
  ;; This whole block if, correct, doesn't amount to any result
  (if (null lst)
      acc
    (if (atom (car lst))
        (append 'x acc)
      (if (consp (car lst))
          (append (cons 'x 'x) acc)
        (if (listp (car lst))
            (append (exify-aux (car lst) nil) acc)
          (if (eq (car lst) nil)
              (append nil acc))))))

  ;; This is the tail call and it's called unconditionally
  (exify-aux (cdr lst) acc))

Вам нужно быть более близким с cons.

(defun exify (tree)
  (cond ((null tree) nil)
        ((atom tree) 'x)
        (t (cons (exify (car tree)) 
                 (exify (cdr tree))))))

Когда вы находитесь, вы можете выполнять функции более высокого порядка:

(defun exify (tree) 
  (accumulate-tree tree  
                   (lambda (_) 'x) ; replaces all non nil leafs with x
                   #'cons          ; copies branches 
                   nil))           ; copies empty leafs

Накопительное дерево можно определить так:

(defun accumulate-tree (tree term combiner null-value)
  (labels ((rec (tree)
             (cond ((null tree) null-value)
                   ((atom tree) (funcall term tree))
                   (t (funcall combiner (rec (car tree)) 
                                        (rec (cdr tree)))))))
    (rec tree)))
2
Sylwester 4 Янв 2016 в 03:53

(append 'x acc)

Как это должно работать? Добавлять принимает списки. x - это символ.

Кроме того, какова цель (append nil acc)? Добавление пустых списков не дает ничего полезного. (append '() '() '() '()) - это просто ().

2
Rainer Joswig 3 Янв 2016 в 22:46