#scheme #lisp #circular-reference #guile
#схема #lisp #циклическая ссылка #хитрость
Вопрос:
Я тестировал этот код в guile:
> (define xxx (let ((x '(1 2 3))) (set-cdr! (cddr x) x) x))
> xxx
это отображение (1 2 3)
но это:
(define x '(1 2 3))
(set-cdr! (cddr x) x)
x
=> (1 2 3 . #-2#)
создает циклический список
Почему первый код не работает в guile? Если вы не знаете о guile, я просто хочу знать, должно ли это работать в соответствии со спецификацией scheme, не знаю, где искать такие вещи.
Комментарии:
1. «это отображение (1 2 3)» — опять же, нет, это не так. Выдает ошибку:
In procedure set-cdr!: Wrong type argument in position 1 (expecting mutable pair): (3)
. Какую версию guile вы используете?2. Они дают тот же самый, циклический, результат в Guile 2.0.13 здесь . Я считаю, что 2.0 был довольно далек от соответствия каким-либо стандартам Scheme.
3. Ни одна из них не является допустимой схемой, поскольку вы пытаетесь изменить литеральные данные в постоянных кавычках. Таким образом, если бы реализация была напечатана
"BaNaNa"
, это все равно было бы нормально.
Ответ №1:
Проблема с вашими примерами в том, что они не работают. Ни один из них. Я понятия не имею, как вернулся первый (1 2 3)
. Но когда вы исправляете одну и ту же проблему в обоих примерах, они работают должным образом и создают круговой список.
Проблема?
'(1 2 3)
и (quote 1 2 3)
это нечто совсем другое, чем (list 1 2 3)
. Они оба «выглядят» одинаково, но первый из них — статический список, и вы не можете его изменить. Вы можете изменять только список, созданный с помощью list
функции (ну и cons
).
Исправить:
(define xxx
(let ((x (list 1 2 3)))
(set-cdr! (cddr x) x)
x))
xxx ;; => (1 2 3 . #-2#)
И то же самое касается второго примера:
(define x (list 1 2 3))
(set-cdr! (cddr x) x)
Пожалуйста, протестируйте свой код перед публикацией.
Комментарии:
1. Второй код работал в guile, это был точный код, который я тестировал, возможно,
(quote 1 2 3)
работает по-другому при использовании сdefine
. Тогда не знал, что это'(1 2 3)
по-другому(list 1 2 3)
. Но еслиquote
работать по-другому, тоlist
тогда почему это работает(let ((x '(1 2 3))) (append! x '(10)))
?2. Я тестировал это также на guile (версия 2.2.4). И я получал сообщение об ошибке. Не знаю, почему ваш guile работает по-другому.
3. Позже guile получил защиту памяти и ошибки. Более старая версия не имеет такой защиты.