Тестирование, являются ли две пары (клетки cons) одинаковыми

Следующая функция из pg 150 Seasoned Schemer устанавливает, имеют ли два списка одинаковую идентичность (то есть занимают одну и ту же память), изменяя cdr каждого списка и затем проверяя, повлияло ли изменение на оба:

(define same?
 (lambda (c1 c2)
   (let ((t1 (cdr c1))
         (t2 (cdr c2)))
     (set-cdr! c1 1)
     (set-cdr! c2 2)
     (let ((v (= (cdr c1) (cdr c2))))
       (set-cdr! c1 t1)
       (set-cdr! c2 t2)
       v))))

Теперь, если я определю a_list следующее:

(define a_list (list 'a 'b 'c 'd))

и оценить

(same? a_list (cdr a_list))

функция возвращает #f, и отладчик (доктор Ракет) подтверждает, что эти два списка - которые должны совместно использовать большинство их членов, поскольку второй аргумент является правильным подмножеством первого - на самом деле имеют разные копии те же члены. Как это возможно?!

Для небольшого поворота этой идеи:

(set-cdr! (cddr a_list) a_list)

Сейчас a_list цикличен Если я проверю эту функцию с same? он регистрирует только #t, когда два аргумента находятся в фазе, т.е. (same? a_list a_list) а также (same? a_list (cdddr a_list)),

[РЕДАКТИРОВАТЬ Ответ находится внизу цепочки комментариев принятого поста]

1 ответ

Решение

same? Функция не проверяет, имеют ли два списка общие элементы. Он проверяет, являются ли две пары (то есть две cons -ячейки) одинаковыми.

В (define a_list (list 'a 'b 'c 'd)) у вас есть 4 пары. В (same? a_list (cdr a_list)) вы проверяете, являются ли первая и вторая пара одной и той же парой, и поскольку они неsame? возвращается #f,

Что касается:

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

Можете ли вы быть более точным о том, как вы проверяете это в DrRacket?

Два списка a-list и (cdr a-list) делят участников.

РЕДАКТИРОВАТЬ:

предполагать c1 а также c2 являются названиями для двух разных минусов:

c1: (foo . bar)      c2:  (baz . qux)

Теперь мы оцениваем (set-cdr! c1 1) и получить:

c1: (foo . 1)      c2:  (baz . qux)

Теперь мы оцениваем (set-cdr! c2 2) и получить:

c1: (foo . 1)      c2:  (baz . 2)

Затем мы сравниваем cdrs с (= (cdr c1) (cdr c2)), Так как cdrs разные, мы получаем #f,

Вывод: когда минусы разные, одинаковые? возвращает #f.


Теперь предположим c1 а также c2 являются названиями для одной и той же минусовой ячейки:

c1 = c2: (foo . bar)

Теперь мы оцениваем (set-cdr! c1 1) и получить:

c1 = c2: (foo . 1)  

Теперь мы оцениваем (set-cdr! c2 2) и получить:

c1 = c2: (foo . 2)  

Затем мы сравниваем cdrs с (= (cdr c1) (cdr c2)), Так как cdrs одинаковы, мы получаем #t,

Вывод: когда минусы одинаковые, same? возвращается #f,

РЕДАКТИРОВАТЬ 2

Чтобы проверить, есть ли минусы c является одной из минусов клетки l использовать этот:

(define (loop c l)
  (cond
    [(null? l) #f]
    [(same? c l) #t]
    [else (loop c (cdr l))]))
Другие вопросы по тегам