2015-08-02 2 views
-1

Почему следующий фрагмент кода печатает nil вместо последнего элемента?Странный результат elisp while

(progn 
    (setq lst '(3 5 7)) 
    (while (not (equal lst (car lst))) 
    (setq lst (cdr lst))) 
    ;; BODY 
    (print lst)) 

Примечание: мне нужно обработать последний элемент иначе, чем остальная часть списка.

+0

'(равный lst (cdr lst))' действует только для пустого списка. Мои плохие навыки LISP говорят мне, что это, вероятно, должно быть «(равно lst (car lst))». –

+0

Моя ошибка. с «автомобилем» тот же результат. – jone

+0

@HristoIliev: '(equal lst (car lst))' is * also * only true для пустого списка (и некоторых странных круговых списков, но пока не будем игнорировать их ...). – npostavs

ответ

1

Потому что cdr последнего элемента - nil, и вы устанавливаете переменную на это.

Как правило, car каждого cons является значением (которое может быть указателем на другой список), а cdr является указателем на оставшуюся часть списка. Поэтому, когда вы просматриваете список, вы обычно хотите работать на car.

(progn 
    (setq lst '(3 5 7)) 
    (while (cdr lst)) 
    (setq lst (cdr lst))) 
    (print (car lst))) 

Любой основной Lisp введение будет иметь лучшие зрительные образы, чем у меня, но если вы читали один, это должно выглядеть знакомым. Основным строительным блоком списка является ячейка cons с car и cdr (имена, по-видимому, сохраняют имена регистров, используемые в первых реализациях Lisp).

+------+------+ 
| car | cdr | 
+------+------+ 

Ваш список с тремя элементами будет иметь три conses; (3 . (5 . (7 . nil))) или графический

+---+---+ +---+---+ +---+---+ 
| . | o--->| . | o--->| . | o---# 
+-v-+---+ +-v-+---+ +-v-+---+ 
    3   5   7 

Так car первых минусов есть (указатель) значение 3, а его cdr есть (указатель) на следующий cons в списке.

Смежные вопросы