Говоря в ближайшем будущем, относится ли (= 'a' a) к тому же атому? - PullRequest
6 голосов
/ 07 сентября 2010

В некоторых реализациях Common LISP мы можем сказать, что для следующего выражения

(eq 'a 'a)

равно true, потому что 'a и 'a являются "одним и тем же атомом".

Это может зависеть от реализации, но, похоже, фраза (используемая в популярной учебной книге LISP) предполагает, что атомы одного и того же значения хранятся в одном и том же месте в памяти.

В Java две интернированные строки одного и того же значения хранятся в одном и том же месте в памяти.

Теперь Clojure в JVM наследует наследие Java, но верно ли сказать, что два атома в Clojure (в JVM), имеющие одинаковое значение, являются одним и тем же атомом? (т.е. как работает механизм хранения атомов Clojure?)

Ответы [ 4 ]

20 голосов
/ 07 сентября 2010

Во-первых, «атом» имеет другое значение в Clojure, чем в большинстве других Лиспов.См. http://clojure.org/atoms

Функция Clojure = использует равенство значение .Таким образом, два объекта с одинаковыми значениями будут =, даже если они хранятся в разных местах в памяти.

Чтобы проверить, являются ли два объекта на самом деле одним и тем же объектом, по одному адресу в памяти, используйте identical? функция.

6 голосов
/ 07 сентября 2010

Я думаю, что 'a' и 'a будут разными объектами Java под капотом. Я считаю, что это подтверждает это подозрение:

user> (def foo 5)
#'user/foo
user> (System/identityHashCode 'foo)
578999228
user> (System/identityHashCode 'foo)
1724482638

Если вы посмотрите на фактическую реализацию Symbol в Clojure, вы увидите, что символ состоит из пространства имен и имени, и эти строки ДОЛЖНЫ быть интернированными строками. Метод Symbol.equals () полагается на проверку идентичности этих двух строк, полагаясь на строку intern.

4 голосов
/ 07 сентября 2010

Чтобы добавить ответы Алекса и Стюарта, нельзя сделать символы в Clojure равными identical?, если они равны =, в основном потому, что они могут содержать метаданные.Два символа, которые имеют одинаковые компоненты .name и .namespace, но разные метаданные, будут =, но не identical?.

Вещи можно было бы упорядочить таким образом, чтобы два символа с одинаковыми метаданными, пространством имен иимя всегда будет identical?, но это (1) два больших хлопот без реальной выгоды (так как у вас все еще будут некоторые символы =, но не identical?), (2) вопреки идее, что типы, которыеМожет нести метаданные, как правило, должны сравниваться для значения равенства (в которое метаданные не вносят вклад), в то время как фактическое равенство указателей должно быть зарезервировано для особых ситуаций (в основном, с взаимодействием).

Обратите внимание, что ключевые слова Clojure являются отдельнымкоторый = действительно эквивалентен identical?.(Очевидно, что к ним не могут быть прикреплены метаданные.)

4 голосов
/ 07 сентября 2010

Я объясню часть Common Lisp:

В Common Lisp (eq 'a' a) всегда возвращает T.

Причина: во время чтения читатель ищет a , и для обоих a он ищет один и тот же символ a . Поскольку любой символ является эквалайзером сам по себе, выражение всегда возвращает T.

Это верно для большинства типов объектов, но с некоторыми исключениями. Цифры и символы, например, не являются обязательными EQ в Common Lisp. Причиной этого является эффективность. Чтобы сравнить их, если они имеют одинаковое число или одинаковый символ, можно использовать функцию EQL.

...