2014-02-09 2 views
2

Рассмотрим минусы x1:Emacs Lisp совместно структура и общие ссылки

(setq x1 '(a . (b c))) => (a b c) 

или в списке обозначений:

(setq x1 '(a b c)) => (a b c) 

и минусы x2, построенные на x1:

(setq x2 (cons 'A (cdr x1))) => (A b c) 

cons help (в Emacs) говорит, что функция creat es a новый минус, дает ему аргументы, 'A и (cdr x1), как компоненты и возвращает его. В этом нет ничего, что говорит о том, что жизнь вновь возвращенных минусов будет связана с с ее генерирующими компонентами.

Во всяком случае, если один изменяет копию, x2, также отправляющая минусы, (a . (b c)) модифицируется:

(setcar (cdr x2) 'B) => B 
x2 => (A B c) ; as from the assignment 
x1 => (a B c) ; x1 and x2 are linked 

Другие примеры функции могут показать связь между x1 и x2.

(setq x1 '(a . (b c))) => (a b c) 
(setq x2 (cons 'A (cdr x1))) => (A b c) 
(nreverse x2) => (c b A) 
x1 => (a b A) 

Я взял этот пример из документации setcar в Emacs Lisp Reference Manual, в котором говорится, что «минусы ячейка является частью общей структуры» и корд из x1 и x2 упоминается как " общая ссылка»и x1, x2 графически показано, как (слегка адаптированный):

x1: 
    --------------  --------------  -------------- 
    | car | cdr |  | car | cdr |  | car | cdr | 
    | a | o------->| b | o------->| c | nil | 
    |  |  | -->|  |  |  |  |  | 
    -------------- | --------------  -------------- 
        | 
    x2:    | 
    -------------- | 
    | car | cdr | | 
    | A | o---- 
    |  |  | 
    -------------- 

Это что-то напоминает указатели C, в том, что корд из x2 не копия, а„точки“в ВСЗ x1. Ясно, но мне интересно, когда эта ситуация возникает практически, т. Е. , как я могу узнать, указывает ли (элемент) минусы на другой или представляет собой собственную копию? В общем, что (где) является формальным определением общая структура и общие ссылки?

В Справочном руководстве Emacs Lisp нет явного упоминания о них. Фактически поиск «общего» или «ссылки» в своем индексе возвращает (за исключением файлов/веб-ссылок) только косвенную ссылку на «общую структуру, синтаксис чтения», касающийся их представления, а не на то, что они есть.
Любопытный поиск в PDF для «общих» земель, как первое вхождение, в раздел «Чтение синтаксиса для круглых объектов», начиная с «Представлять общие или круговые структуры ...». К сожалению, ранее не упоминаются слова общие и круговые (структуры)! Следующим случаем является упомянутая документация setcar.

Таким образом, кажется, что есть неявные указатели в Lisp/Elisp, но никто не хочет говорить о них.))

+0

Вводные книги Lisp должны объяснять, как составлены списки из cons-клеток. Ячейка cons в основном представляет собой структуру данных с двумя указателями (минус некоторые оптимизации). Это ничего нового - так было в самом первом Лиспе, более пятидесяти лет назад. Создание списков и другой структуры данных из ячеек cons и функций, которые их используют, лежит в основе Lisp. Похоже, вы хорошо начали. –

+0

@RainerJoswig: Комментировать split: ** Part1 **. Пожалуйста, посмотрите здесь: [psg.com/~dlamkins](http://psg.com/~dlamkins/sl/chapter11.html). «деструктивная функция, такая как NREVERSE * иногда *, изменяет свой аргумент таким образом, что измененный аргумент идентичен результату функции». Иногда? Когда? – antonio

+0

@RainerJoswig: Комментировать split: ** Part2 ** «вы не должны зависеть от побочных эффектов DELETE. [...] Но некоторые макросы, например PUSH и POP, принимают место в качестве аргумента и * организуют обновить * место с правильным значением. " Большое спасибо автору, но документация должна указывать на это с той же ясностью. В документах Emacs не указано, что 'delete' является ненадежным, а' push'/'pop' преуспевает в модификации задействованных объектов. Кроме того, в чем смысл деструктивной функции с побочными эффектами, если вы не можете зависеть от них? они быстрее или меньше потребляют память? – antonio

ответ

4

Ваши друзья функции eq and equal.

eq сравнивает физическую идентичность, а equal проверяет, являются ли объекты «похожими».

В вашем случае:

(defvar a (list 1 2 3)) 
(defvar b (cons 1 (cdr a))) 
(equal a b) 
==> t 
(eq a b) 
==> nil 
(eq (cdr a) (cdr b)) 
==> t 

EDIT: обратите внимание, что list is equivalent to a few cons calls:

(list x y) == (cons x (cons y nil)) 

и всякий раз, когда вы звоните cons или list, вы получите то, что является неeq к ничего еще ,

Продолжая пример выше:

(defvar c (list 4 (cdr a))) 
(defvar d (list 4 (cdr b))) 
(equal c d) 
==> t 
(eq c d) 
==> nil 
(eq (cdr c) (cdr d)) 
==> nil 
(eq (cadr c) (cadr d)) 
==> t 
(eq (cadr c) (cdr a)) 
==> t 
(eq (cadr d) (cdr b)) 
==> t 

PS. Полезно понять, что (E x y) ==> (E (F x) (F y)), где E является предикатом равенства (eq или equal) и F является аксессуаром (например, car или cdr).

PPS. Обратное верно для equal:

(and (equal (car x) (car y)) 
    (equal (cdr x) (cdr y))) 

следует (на самом деле, эквивалентно) (equal x y); но не для eq.

+0

Спасибо, что дает очень общий способ тестирования ссылок. Я до сих пор не понимаю причины. Например, задано снова '(setq x1 '(abc))', с функцией 'cons' я получаю' (setq a1 (cons' A (cdr x1))), '(setq a2 (cons 'A (cdr x1))) ',' (eq (cdr a1) (cdr a2)) => t', но используя функцию 'list', я получаю' (setq a1 (list 'A (cdr x1))), '(setq a2 (список 'A (cdr x1)))', '(eq (cdr a1) (cdr a2)) => nil'. В обоих случаях 'a1' /' a2' являются 'type-of' cons, они разделяют * same * cdr, resp. '(b c)' и '((b c))'; но в первом случае они являются «eq», а во втором они не являются «eq». – antonio

+1

@antonio: вам не хватает основной разницы между 'list' и' cons'. см. править – sds

0

Чтобы добавить @ ответ ИКБ, так как он не упоминал об этом в явном виде, и вы об этом спросили:

Смотрите руководство Elisp, узел Modifying Lists и его подузлы. Пример вы спрашиваете о упоминаются явно в узле Setcar:

;; Create two lists that are partly shared. 
(setq x1 '(a b c)) 
     => (a b c) 
(setq x2 (cons 'z (cdr x1))) 
     => (z b c) 

Да, ваш вопрос не конкретно о setcar и другие структуры списка модифицирующих функций. Но презентация в руководстве Elisp о cons cells дает ответ, который вы ищете в целом, в дополнение к комментариям и ответам, приведенным здесь, о том, как аргументы передаются в Lisp.

+0

Я написал, что мой пример взят из документации 'setcar', и, поскольку это единственная ссылка, которую я нашел для такого релевантного предмета, я спрашивал, где найти больше информации, а также, если есть какой-то концептуальный способ сделать вывод, когда объект будет связан с другим. – antonio

+0

antonio: FWIW, «указатель» проиндексирован в руководстве и переводит вас в 'C-h i g'' (elisp) Cons Cell Type'' RET'. Я понимаю, что это несколько касательно вашего фактического вопроса, и вы почти наверняка его охватили; но убедитесь, что прочитали этот раздел, если вы еще этого не сделали. – phils

0

Здесь есть несколько других ответов, которые объясняют это более подробно, но было бы полезно также ориентироваться на очень минимальную аналогию. A cons cell - очень маленький контейнер: он содержит два элемента и имеет аксессуар car и cdr для получения этих элементов.

В большинстве объектно-ориентированных языков программирования автоматическое копирование объектов при их вставке в контейнер отсутствует. Например, в Java, если у вас есть:

Object a = new Object(); 
Object b = new Object(); 

Object[] cons1 = new Object[] { a, b }; 
Object[] cons2 = new Object[] { a, b }; 

Вы должны ожидать

cons1 == cons2 

быть ложным, но

(cons1[0] == cons2[1]) && (cons1[1] == cons2[1]) 

, чтобы быть правдой. Контейнеры объекты разные, но объекты, которые они содержат, одинаковы.

Это просто соглашение, что списки построены из минусов ячеек, используя, где список либо пустой список (nil), или клетка, против которого car является первым элементом списка и чья cdr является остальной частью списка ,

Это что-то напоминает указатели C, в том, что корд из х2 не копия, а «точки» на корд х1. Ясно, но мне интересно, когда эта ситуация практически возникает, то есть, как я могу узнать, является ли элемент ( ) минусами, указывающими на другой или представляет собой самообучающуюся копию? В общем, что (где) является формальным определением общей структуры и общих ссылок?

Это не просто напоминает, это почти то же самое. В памяти есть объект, и вы можете получить их. Иногда более чем одна вещь может иметь ссылку на один и тот же объект в памяти. Вы можете проверить соответствие cons ячеек с eq, но это не общий ответ об общей структуре, потому что у вас нет способа узнать, кто еще имеет ссылку на объект. В общем, вы будете следовать правилу в строках «не изменяйте структуры, которые вы не создали, если вы явно не упоминаете об этом в документации, и даже тогда, верните важное значение». Таким образом, reverse не изменяет свой аргумент, но nreverse разрешено (но все же возвращает обратный список, nreverse не гарантирует, что список отменен на месте). Если вы создаете список, который является локальным для вашей функции, отлично использовать nreverse, чтобы отменить его, потому что вы знаете, что никто не имеет ссылки на него.