Ожидается, что идентичность возвращает что-то другое из своего аргумента?

Вот пример где запрос идентичность изменяет возвращенную стоимость, которая, кажется, мне указывает, что docstring "Возвращает свой аргумент". не совершенно верно:

(let [x Double/NaN] (identical? x x)) ;=> false
(let [x (identity Double/NaN)] (identical? x x)) ;=> true

Это ожидается? Или действительно ли это - ошибка с идентичность функция так или иначе?

5
Это происходит, вероятно, из-за бокса - Double/ NaN возвращает примитив дважды , который заперт дважды в первом примере, но только однажды во втором.
добавлено автор Lee, источник

6 ответы

You appear to have found an edge case involving identity, identical?, and primitive vs object equality. Note that in Java, java.lang.Double/NaN is a primitive:

public static final double NaN

Но идентичный сравнивает Явские Объекты:

; clojure.core
(defn identical?
  "Tests if 2 arguments are the same object"
  {:inline (fn [x y] `(. clojure.lang.Util identical ~x ~y))
   :inline-arities #{2}
   :added "1.0"}
  ([x y] (clojure.lang.Util/identical x y)))

// clojure/lang/Util.java
static public boolean identical(Object k1, Object k2){
    return k1 == k2;
}

Попробуйте эту уловку, чтобы вынудить NaN в Двойной объект вместо распакованного примитива:

tupelo.core=> (let [x (Double. Double/NaN)] 
  (spyxx x) 
  (identical? x x))

x => java.lang.Double->NaN
true

Я подозреваю, что автобокс примитивного NaN, который может не произойти с различными примерами использования, является причиной различий, которые вы видите.

8
добавлено
Уловка в конце - просто то же самое как, что спрашивает этот вопрос: вы втискиваете NaN в Двойном, как идентичность делает в вопросе. It' s не действительно другая вещь. Я думаю единственная вещь, которую пропускает этот ответ, объяснение почему оба идентичность и идентичный ? влекут за собой автобокс.
добавлено автор amalloy, источник

You appear to have found an edge case involving identity, identical?, and primitive vs object equality. Note that in Java, java.lang.Double/NaN is a primitive:

public static final double NaN

Но идентичный сравнивает Явские Объекты:

; clojure.core
(defn identical?
  "Tests if 2 arguments are the same object"
  {:inline (fn [x y] `(. clojure.lang.Util identical ~x ~y))
   :inline-arities #{2}
   :added "1.0"}
  ([x y] (clojure.lang.Util/identical x y)))

// clojure/lang/Util.java
static public boolean identical(Object k1, Object k2){
    return k1 == k2;
}

Попробуйте эту уловку, чтобы вынудить NaN в Двойной объект вместо распакованного примитива:

tupelo.core=> (let [x (Double. Double/NaN)] 
  (spyxx x) 
  (identical? x x))

x => java.lang.Double->NaN
true

Я подозреваю, что автобокс примитивного NaN, который может не произойти с различными примерами использования, является причиной различий, которые вы видите.

8
добавлено
Уловка в конце - просто то же самое как, что спрашивает этот вопрос: вы втискиваете NaN в Двойном, как идентичность делает в вопросе. It' s не действительно другая вещь. Я думаю единственная вещь, которую пропускает этот ответ, объяснение почему оба идентичность и идентичный ? влекут за собой автобокс.
добавлено автор amalloy, источник

Добавить немного цвета к ответу Алана на боксе:

Можно хотеть изучить == функция, которая осуществляется этот путь:

public boolean equiv(Number x, Number y){
    return x.doubleValue() == y.doubleValue();
}

Это выполняет примитивное сравнение двух фактических дважды s. Ваш пример, с == :

(let [x (identity Double/NaN)] (== x x))
=> false
(let [x (identity Double/POSITIVE_INFINITY)] (== x x))
=> true

Что продолжается? Почему NaN == NaN ложный? Ну, примитивное сравнение, используя == должен на самом деле возвратиться ложный для NaN . Это странно определило этот путь в IEEE 754 и Ява ведет себя этот путь. Это - единственное "число", которое, когда по сравнению с собой, не равняется себе.

Как в стороне, чтобы видеть, как равенство объекта может быть странной вещью на Яве, посмотрите это:

(identical? 127 127)
=> true
(identical? 128 128)
=> false

Это вызвано тем, что Ява прячет первое про запас 2^8 неподписанный ints, таким образом, 127 s быть сравненным тот же самый объект в первом примере, но 128 s во втором примере различные объекты. Так, есть некоторые gotchas, чтобы знать с проверкой равенство!

Но главная еда на дом здесь: <�кодовая> идентичность работает, как это должно! Просто будьте осторожны, сравнивая вещи, поскольку понятие "равенства" не таким образом прямо!

3
добавлено
Этот doesn' t отвечают на вопрос, который является о том, что возвращенные ценности отличаются друг от друга, а не о том, каковы определенно те возвращенные ценности.
добавлено автор Sam Estep, источник

Добавить немного цвета к ответу Алана на боксе:

Можно хотеть изучить == функция, которая осуществляется этот путь:

public boolean equiv(Number x, Number y){
    return x.doubleValue() == y.doubleValue();
}

Это выполняет примитивное сравнение двух фактических дважды s. Ваш пример, с == :

(let [x (identity Double/NaN)] (== x x))
=> false
(let [x (identity Double/POSITIVE_INFINITY)] (== x x))
=> true

Что продолжается? Почему NaN == NaN ложный? Ну, примитивное сравнение, используя == должен на самом деле возвратиться ложный для NaN . Это странно определило этот путь в IEEE 754 и Ява ведет себя этот путь. Это - единственное "число", которое, когда по сравнению с собой, не равняется себе.

Как в стороне, чтобы видеть, как равенство объекта может быть странной вещью на Яве, посмотрите это:

(identical? 127 127)
=> true
(identical? 128 128)
=> false

Это вызвано тем, что Ява прячет первое про запас 2^8 неподписанный ints, таким образом, 127 s быть сравненным тот же самый объект в первом примере, но 128 s во втором примере различные объекты. Так, есть некоторые gotchas, чтобы знать с проверкой равенство!

Но главная еда на дом здесь: <�кодовая> идентичность работает, как это должно! Просто будьте осторожны, сравнивая вещи, поскольку понятие "равенства" не таким образом прямо!

3
добавлено
Этот doesn' t отвечают на вопрос, который является о том, что возвращенные ценности отличаются друг от друга, а не о том, каковы определенно те возвращенные ценности.
добавлено автор Sam Estep, источник

Действительно идентичность "возвращают его аргумент" ?

Это зависит, что вы подразумеваете под аргументом .

  • , Если это - оцененное выражение в форме вызова функции , тогда не всегда .
  • , Если это , что тело функции видит на стеке после входа , тогда да, это делает .

Аномалия возникает из-за способа, которым Клоджьюр вызывает функции.

  • Clojure functions are objects that comply with the IFn interface.
  • A Clojure function call translates into one of the many invoke methods - overloaded for arity - of the function object.
  • All of the invoke methods have Object parameters.

Результат всего этого - то, что каждый вызов функции Clojure переводит свой каждый аргумент на некоторый Объект - операция по идентичности за исключением примитивов, которые обернуты в соответствующий Явский класс: долго в Лонг , и так далее.

Таким образом, даже идентичность функция, по существу (defn идентичность [x] x) , не возвращает примитивный аргумент. Это не может, потому что это никогда не видит его.


Например, давайте рассмотрим выражение

(inc 3)

Число 3 является, конечно, долго . Что тип (inc 3) ? Давайте спросим Clojure:

(type (inc 3))
=> java.lang.Long

... , запертые Лонг объект.

Держитесь, действительно ли мы уверены, что 3 является примитивом долго ?:

(type 3)
=> java.lang.Long

Aaaaaaagh! Это заперто также!

Not necessarily! You can't tell, because by the time the body of type sees 3, it is boxed, whether or not it was so to the reader/compiler. The Clojure documentation is silent on the point. It just says that numeric literals are generally represented as per Java.

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

То, что показывает ваш пример, - то, что примитивы считаются как таковыми, распакованными, по крайней мере в , которому позволяют формы:

(let [x 1.0] (identical? x x)) ;=> false
(let [x (identity 1.0)] (identical? x x)) ;=> true

Факт, который идентичный ? в состоянии различать два бокса 1.0 показывает, что это проводится как примитив дважды . (Я использовал дежурное блюдо дважды , только чтобы показать, что поведение не имеет отношения к специальной стоимости Double/NaN ).

Теперь давайте попытаемся поместить число в вар:

(def x 1.0)

(identical? x x) ;=> true
(let [x (identity x)] (identical? x x)) ;=> true

Это заперто.

В то время как мы здесь, автобокс - идемпотент:

(identical? x (identity x)) ;=> true

Вышеупомянутое добавляет мало к какой Алан Томпсон и Джош answers и Alan Malloy's и Lee's comments comprise. I just felt they had hooked и played the fish, without actually landing it.

0
добавлено

Действительно идентичность "возвращают его аргумент" ?

Это зависит, что вы подразумеваете под аргументом .

  • , Если это - оцененное выражение в форме вызова функции , тогда не всегда .
  • , Если это , что тело функции видит на стеке после входа , тогда да, это делает .

Аномалия возникает из-за способа, которым Клоджьюр вызывает функции.

  • Clojure functions are objects that comply with the IFn interface.
  • A Clojure function call translates into one of the many invoke methods - overloaded for arity - of the function object.
  • All of the invoke methods have Object parameters.

Результат всего этого - то, что каждый вызов функции Clojure переводит свой каждый аргумент на некоторый Объект - операция по идентичности за исключением примитивов, которые обернуты в соответствующий Явский класс: долго в Лонг , и так далее.

Таким образом, даже идентичность функция, по существу (defn идентичность [x] x) , не возвращает примитивный аргумент. Это не может, потому что это никогда не видит его.


Например, давайте рассмотрим выражение

(inc 3)

Число 3 является, конечно, долго . Что тип (inc 3) ? Давайте спросим Clojure:

(type (inc 3))
=> java.lang.Long

... , запертые Лонг объект.

Держитесь, действительно ли мы уверены, что 3 является примитивом долго ?:

(type 3)
=> java.lang.Long

Aaaaaaagh! Это заперто также!

Not necessarily! You can't tell, because by the time the body of type sees 3, it is boxed, whether or not it was so to the reader/compiler. The Clojure documentation is silent on the point. It just says that numeric literals are generally represented as per Java.

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

То, что показывает ваш пример, - то, что примитивы считаются как таковыми, распакованными, по крайней мере в , которому позволяют формы:

(let [x 1.0] (identical? x x)) ;=> false
(let [x (identity 1.0)] (identical? x x)) ;=> true

Факт, который идентичный ? в состоянии различать два бокса 1.0 показывает, что это проводится как примитив дважды . (Я использовал дежурное блюдо дважды , только чтобы показать, что поведение не имеет отношения к специальной стоимости Double/NaN ).

Теперь давайте попытаемся поместить число в вар:

(def x 1.0)

(identical? x x) ;=> true
(let [x (identity x)] (identical? x x)) ;=> true

Это заперто.

В то время как мы здесь, автобокс - идемпотент:

(identical? x (identity x)) ;=> true

Вышеупомянутое добавляет мало к какой Алан Томпсон и Джош answers и Alan Malloy's и Lee's comments comprise. I just felt they had hooked и played the fish, without actually landing it.

0
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Clojure — русскоговорящее сообщество
Clojure — русскоговорящее сообщество
433 участник(ов)

Общаемся на темы, посвященный Clojure. Решаем проблемы, обмениваемся опытом и делимся новостями. Вакансии и поиск работы: @clojure_jobs Вам могут быть интересны: @javascript_ru, @nodejs_ru, @ruby_ru, @devops_ru, @devops_jobs