Тестирование, являются ли две пары (клетки 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))]))