アイデンティティーがその主張とは異なる何かを返すことが予想されますか?

identity を呼び出すと返される値が変わる例は次のとおりです。 docstringが "その引数を返す"ことを示すために私には完全に真実ではない:

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

これは予想されますか?それともどういうわけか identity 機能のバグですか?

5
これはおそらくボクシングによるものです - Double/NaN は、最初の例では2回ボックス化されていますが、2番目には1回しか double というプリミティブを返します。
追加された 著者 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

しかし、Javaオブジェクトは同じです。

; 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をボックス化されていないプリミティブの代わりにDoubleオブジェクトにすることができます。

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

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

さまざまなユースケースで発生する可能性がある、または発生しない可能性がある原始的なNaNのオートボクシングが、表示されている違いの原因であると私は考えています。

8
追加された
最後のトリックは、この質問が尋ねているのと同じことです。アイデンティティーが質問でそうであるように、あなたはダブルでNaNをボックスに入れる。それは本当に違うことではありません。この答えが欠けているのは、 identity同一の両方がオートボクシングを必要とする理由の説明だけです。
追加された 著者 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

しかし、Javaオブジェクトは同じです。

; 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をボックス化されていないプリミティブの代わりにDoubleオブジェクトにすることができます。

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

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

さまざまなユースケースで発生する可能性がある、または発生しない可能性がある原始的なNaNのオートボクシングが、表示されている違いの原因であると私は考えています。

8
追加された
最後のトリックは、この質問が尋ねているのと同じことです。アイデンティティーが質問でそうであるように、あなたはダブルでNaNをボックスに入れる。それは本当に違うことではありません。この答えが欠けているのは、 identity同一の両方がオートボクシングを必要とする理由の説明だけです。
追加された 著者 amalloy,

ボクシングに関するアランの答えに少し色を追加するには:

このように実装されている == 関数を調べてみてください。

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

これは2つの実際の double の基本的な比較を実行します。あなたの例、 ==

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

どうしたの? NaN == NaN が間違っているのはなぜですか。さて、 == を使用した基本的な比較では、実際には NaN に対してfalseが返されるはずです。これは IEEE 754 でこのように奇妙に指定されており、Javaはこのように動作します。それはそれ自体と比較したとき、それ自体と等しくない唯一の「数」です。

余談ですが、オブジェクトの同等性がJavaで奇妙なことになる可能性があることを確認するには、以下を参照してください。

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

これは、最初の2 ^ 8個の符号なし整数がjavaによってキャッシュされるため、比較される 127 は最初の例と同じオブジェクトですが、2番目の例では 128 異なるオブジェクトです。ですから、平等をチェックする際に注意すべきことがいくつかあります。

しかし、ここでの主な問題は、 identity が正常に機能していることです。 「平等」の概念はそれほど単純ではないので、物事を比較するときは注意してください。

3
追加された
これは質問に答えません。それは戻り値が互いに異なるという事実に関するものであり、それらの戻り値が具体的に何であるかについてではありません。
追加された 著者 Sam Estep,

ボクシングに関するアランの答えに少し色を追加するには:

このように実装されている == 関数を調べてみてください。

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

これは2つの実際の double の基本的な比較を実行します。あなたの例、 ==

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

どうしたの? NaN == NaN が間違っているのはなぜですか。さて、 == を使用した基本的な比較では、実際には NaN に対してfalseが返されるはずです。これは IEEE 754 でこのように奇妙に指定されており、Javaはこのように動作します。それはそれ自体と比較したとき、それ自体と等しくない唯一の「数」です。

余談ですが、オブジェクトの同等性がJavaで奇妙なことになる可能性があることを確認するには、以下を参照してください。

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

これは、最初の2 ^ 8個の符号なし整数がjavaによってキャッシュされるため、比較される 127 は最初の例と同じオブジェクトですが、2番目の例では 128 異なるオブジェクトです。ですから、平等をチェックする際に注意すべきことがいくつかあります。

しかし、ここでの主な問題は、 identity が正常に機能していることです。 「平等」の概念はそれほど単純ではないので、物事を比較するときは注意してください。

3
追加された
これは質問に答えません。それは戻り値が互いに異なるという事実に関するものであり、それらの戻り値が具体的に何であるかについてではありません。
追加された 著者 Sam Estep,

identity "引数を返します"

引数の意味によって異なります。

  • 関数呼び出しフォームで評価された式である場合は、 とは限りません。
  • 入力時に関数本体がスタック上に表示されるものであれば 、そうであればはい

この異常は、Clojureが関数を呼び出す方法によって発生します。

  • Clojure関数は、に準拠したオブジェクトです。 IFn インターフェース
  • Clojure関数呼び出しは、多数の呼び出しのうちの1つに変換されます。 メソッド - アリティのためにオーバーロードされた - 関数オブジェクトの。
  • すべての invoke メソッドには、 Object パラメータがあります。

これらすべてをまとめると、すべてのClojure関数呼び出しはそのすべての引数をある種の Object に変換します。これは、対応するJavaクラスでラップされたプリミティブを除く同一操作です。 >から Long へと続きます。

そのため、 identity 関数、基本的に(defn identity [x] x)でも、基本的な引数は返されません。見えないので、できません。


たとえば、次の式を考えましょう。

(inc 3)

3 という数字は確かに long です。 (inc 3)とは何ですか? Clojureに聞いてみましょう:

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

... 箱入り Long オブジェクト。

ちなみに、 3long の基本要素であると確信していますか。

(type 3)
=> java.lang.Long

ああああああ!それも箱入りです!

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.

そのため、一般的には評価メカニズムであり、基本的な引数をボクシングする役割を担う特定の機能( identity など)ではありませんこれはオートボクシングです。

あなたの例が示しているのは、プリミティブは少なくとも let 形式で、そのまま箱に入れられずに保持されているということです。

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

同一? (私は普通の double を使いましたが、その動作が特別な値 Double/NaN と関係ないことを示すためだけに使用しています)

それでは、数値をvarに入れてみましょう。

(def x 1.0)

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

それは箱入りです。

私たちがここにいる間、自動ボクシングはべき等です。

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

Alan Thompsonのジョシュの答えとアランマロイとリーのコメントが含まれています。私はちょうど彼らが実際にそれを着陸させずに、魚を引っ掛けて遊んだのを感じました。

0
追加された

identity "引数を返します"

引数の意味によって異なります。

  • 関数呼び出しフォームで評価された式である場合は、 とは限りません。
  • 入力時に関数本体がスタック上に表示されるものであれば 、そうであればはい

この異常は、Clojureが関数を呼び出す方法によって発生します。

  • Clojure関数は、に準拠したオブジェクトです。 IFn インターフェース
  • Clojure関数呼び出しは、多数の呼び出しのうちの1つに変換されます。 メソッド - アリティのためにオーバーロードされた - 関数オブジェクトの。
  • すべての invoke メソッドには、 Object パラメータがあります。

これらすべてをまとめると、すべてのClojure関数呼び出しはそのすべての引数をある種の Object に変換します。これは、対応するJavaクラスでラップされたプリミティブを除く同一操作です。 >から Long へと続きます。

そのため、 identity 関数、基本的に(defn identity [x] x)でも、基本的な引数は返されません。見えないので、できません。


たとえば、次の式を考えましょう。

(inc 3)

3 という数字は確かに long です。 (inc 3)とは何ですか? Clojureに聞いてみましょう:

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

... 箱入り Long オブジェクト。

ちなみに、 3long の基本要素であると確信していますか。

(type 3)
=> java.lang.Long

ああああああ!それも箱入りです!

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.

そのため、一般的には評価メカニズムであり、基本的な引数をボクシングする役割を担う特定の機能( identity など)ではありませんこれはオートボクシングです。

あなたの例が示しているのは、プリミティブは少なくとも let 形式で、そのまま箱に入れられずに保持されているということです。

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

同一? (私は普通の double を使いましたが、その動作が特別な値 Double/NaN と関係ないことを示すためだけに使用しています)

それでは、数値をvarに入れてみましょう。

(def x 1.0)

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

それは箱入りです。

私たちがここにいる間、自動ボクシングはべき等です。

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

Alan Thompsonのジョシュの答えとアランマロイとリーのコメントが含まれています。私はちょうど彼らが実際にそれを着陸させずに、魚を引っ掛けて遊んだのを感じました。

0
追加された