Схема и вопросы R5RS об экв.

Можете ли вы объяснить, почему первое неверно, а второе верно?

И как это работает? Спасибо.

(eq? '(1 2 3) '(1 2 3)) ;False
(eq? '() '()) ;True

person Honolulu    schedule 22.02.2020    source источник
comment
Вам может быть интересно узнать, что стандарт прямо говорит, что (eq? '() '()) должно быть #t. См.: schemers.org/Documents/Standards/R5RS/HTML.   -  person Flux    schedule 22.02.2020
comment
Результатом (eq? '(1 2 3) '(1 2 3)) может быть любой из #t или #f в зависимости от того, повторно используются литералы реализацией или нет. Это утверждение о том, что оно ложно, не всегда верно.   -  person Sylwester    schedule 22.02.2020


Ответы (2)


Есть только один пустой список, поэтому все случаи использования () относятся к этому списку, а eq? к самому себе. В описании спецификации схемы модели хранилища говорится:

Несмотря на это, понятно, что пустой список не может быть выделен заново, потому что это уникальный объект.

а спецификация eqv? (на которую ссылается описание eq?) говорит, что два объекта эквивалентны, если

obj1 и obj2 — это пустой список

Но когда вы создаете непустой список, он каждый раз создает новый, и они не eq? друг к другу, даже если они содержат одни и те же элементы.

person Barmar    schedule 22.02.2020
comment
на самом деле '() связан с символом, который уникален для всех пустых списков.... поэтому он имеет уникальный адрес. - person alinsoar; 22.02.2020
comment
@alinsoar В Лиспе это символ NIL. Я не думаю, что это правда в Схеме. - person Barmar; 22.02.2020
comment
Я думаю, что это как внутренний символ, а не интернированный символ в массиве, где хранятся видимые пользователю символы. - person alinsoar; 22.02.2020
comment
@alinsoar R7RS говорит, что пустой список — это специальный объект своего типа. - person Barmar; 22.02.2020
comment
Я знаю, что вы правы, и я не хочу противоречить вам. Мое утверждение было похоже на вопрос: ‹‹Не может ли EmptyList рассматриваться как внутренний символ, а не интернированный символ в массиве, где хранятся видимые пользователю символы?›› -- таким образом, что ни один символ, созданный пользователем, никогда не будет попадают по тому же адресу, что и символ, связанный с '()... - person alinsoar; 22.02.2020
comment
Вы можете думать об этом как хотите, но лучше просто думать о нем как о специальном объекте, используемом только для этой цели. Scheme намеренно избегает объединения пустого списка с символом, как это делает Lisp; NIL Лиспа сильно перегружен. - person Barmar; 22.02.2020
comment
На самом деле реализация может повторно использовать литеральные данные, поэтому одни и те же данные в кавычках в разных местах могут быть повторно использованы, создавая (eq? '(1 2 3) '(1 2 3)) ; ==> #t. Это причина, по которой мутация литеральных данных не является схемой, и, следовательно, может случиться что угодно. Большинство реализаций заканчиваются изменением всех повторно используемых мест, где в Racket вы получаете ошибку. - person Sylwester; 23.02.2020

Цитата из TSPL3:

[..] Два объекта считаются идентичными, если они внутренне представлены одним и тем же значением указателя [..] Пустой список () идентичен самому себе, где бы он ни появлялся. [..] Две пары, векторы или строки, созданные различными приложениями cons, vector, string и т. д., различны.

Если вместо этого написать

(let ((x '(1 2 3)))
  (eq? x x))

это будет #t.

person vukung    schedule 22.02.2020
comment
TSPL не является официальным местом для поиска языковых спецификаций. отчеты RNRS. Результат (eq? '(1 2 3) '(1 2 3)) может быть любым из #t или #f и при этом соответствовать спецификациям RNRS. - person Sylwester; 25.02.2020