2017-06-27 12 views
5

यहां एक उदाहरण है जहां identity कॉलिंग लौटा मूल्य बदलता है, जो मुझे इंगित करता है कि डॉकस्ट्रिंग "इसकी तर्क देता है।" पूरी तरह से सच नहीं है:क्या यह उम्मीद की जाती है कि पहचान इसके तर्क से कुछ अलग हो?

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

क्या यह अपेक्षित है? या यह identity फ़ंक्शन किसी भी तरह से एक बग है?

+4

यह शायद मुक्केबाजी के कारण है - 'डबल/नाएन' एक प्राचीन 'डबल' देता है जिसे पहले उदाहरण में दो बार बॉक्स किया जाता है लेकिन केवल एक बार में। – Lee

उत्तर

8

आपको identity, identical?, और आदिम बनाम वस्तु समानता शामिल एक बढ़त मामला मिला है। ध्यान दें कि जावा में, java.lang.Double/NaN is a primitive:

public static final double NaN 

लेकिन समान जावा ऑब्जेक्ट्स तुलना:

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

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

:

; 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 मजबूर करने के लिए इस चाल का प्रयास करें मुझे संदेह है कि आदिम नाइन का ऑटोबॉक्सिंग जो विभिन्न उपयोग-मामलों के साथ हो सकता है/हो सकता है वह अंतर है जो आप देख रहे हैं।

+0

अंत में यह चाल वही बात है जो इस सवाल से पूछ रही है: आप बॉक्स में NaN को डबल में रखते हैं, जैसे कि प्रश्न में पहचान होती है। यह वास्तव में एक अलग बात नहीं है। मुझे लगता है कि इस जवाब में एकमात्र चीज गायब है, यह एक स्पष्टीकरण है कि क्यों 'पहचान' और 'समान' दोनों ऑटोबॉक्सिंग को लागू करते हैं। – amalloy

3

मुक्केबाजी पर अनिल का जवाब देने के लिए कुछ रंग जोड़ने के लिए:

आप == समारोह है, जो इस तरह से कार्यान्वित किया जाता है इस पर गौर कर सकते हैं:

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

यह दो वास्तविक की एक आदिम तुलना करता है double एस। आपका उदाहरण, == साथ:

(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 रों तुलना की जा रही पहले उदाहरण में एक ही वस्तु है, लेकिन दूसरे उदाहरण में 128 एस अलग-अलग ऑब्जेक्ट्स हैं। तो, समानता की जांच के बारे में जागरूक होने के लिए कुछ गठिया हैं!

लेकिन यहां मुख्य अधिग्रहण है: identity यह काम कर रहा है! चीजों की तुलना करते समय सावधान रहें, क्योंकि "समानता" की धारणा इतनी सरल नहीं है!

+0

यह प्रश्न का उत्तर नहीं देता है, जो इस तथ्य के बारे में है कि लौटाए गए मूल्य एक दूसरे से अलग हैं, और विशेष रूप से उन लौटे मूल्यों के बारे में नहीं हैं। –

0

identity"इसकी तर्क वापस करें"?

यह निर्भर करता है कि तर्क द्वारा आपका क्या मतलब है।

  • यदि यह है समारोह कॉल प्रपत्र में मूल्यांकन अभिव्यक्ति, तो हमेशा नहीं।
  • यदि यह है तो फ़ंक्शन का शरीर प्रविष्टि पर स्टैक पर देखता है, तो हाँ, यह करता है।

क्लोजर फ़ंक्शन कॉल करने के तरीके के कारण विसंगति उत्पन्न होती है।

  • क्लोजर फ़ंक्शन वे ऑब्जेक्ट्स हैं जो the IFn interface का अनुपालन करते हैं।
  • एक क्लोजर फ़ंक्शन कॉल फ़ंक्शन ऑब्जेक्ट के - arity के लिए अधिभारित कई invoke विधियों में से एक में अनुवाद करता है।
  • invoke विधियों में से Object पैरामीटर हैं। longLong में, और इतने पर: पुरातन है, जो इसी जावा वर्ग में लिपटे रहे हैं को छोड़कर एक पहचान आपरेशन -

इस सब का नतीजा हर Clojure समारोह कॉल अपने Object किसी तरह का में हर तर्क में अनुवादित करती है ।

तो identity फ़ंक्शन, अनिवार्य रूप से (defn identity [x] x), एक आदिम तर्क नहीं देता है। यह नहीं कर सकता, क्योंकि यह इसे कभी नहीं देखता है।


उदाहरण के लिए, अभिव्यक्ति

(inc 3) 

संख्या 3 निश्चित रूप से एक long है पर विचार करें। (inc 3) किस प्रकार का है? के Clojure पूछते हैं:

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

... एक बॉक्सिंगLong वस्तु।

हैंग पर, कर रहे हैं हम यह सुनिश्चित करें कि 3 एक आदिम long है:

(type 3) 
=> java.lang.Long 

Aaaaaaagh! यह भी बॉक्स किया गया है!

आवश्यक नहीं! आप यह नहीं बता सकते हैं, क्योंकि उस समय तक type3 देखता है, यह बॉक्स किया गया है, चाहे वह पाठक/कंपाइलर के लिए था या नहीं। Clojure documentation बिंदु पर चुप है। यह सिर्फ इतना कहता है कि संख्यात्मक अक्षर आमतौर पर जावा के अनुसार दर्शाए जाते हैं।

तो - सामान्य रूप में - यह मूल्यांकन तंत्र, नहीं (जैसे identity के रूप में) एक विशेष कार्य है कि मुक्केबाजी आदिम तर्क के लिए जिम्मेदार है। यह ऑटो मुक्केबाजी है।

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

तथ्य यह है कि identical?1.0 के दो boxings के बीच भेद करने में सक्षम है यह है कि पता चलता है:

क्या आपके उदाहरण से पता चलता है कि इस तरह के पुरातन, अन-बॉक्सिंग, कम से कम let रूपों में के रूप में आयोजित किया जाता है एक प्राइमेटिव double के रूप में आयोजित किया जाता है। (मैंने एक सामान्य double का उपयोग किया है, यह दिखाने के लिए कि व्यवहार विशेष मान Double/NaN के साथ कुछ भी करने के लिए नहीं है)।

अब एक वर में नंबर डालने की कोशिश करते हैं:

(def x 1.0) 

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

यह बॉक्सिंग रहा है।

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

ऊपर Alan Thompson's और Josh's जवाब और एलन Malloy की और ली की टिप्पणी क्या शामिल करने के लिए थोड़ा जोड़ता है:

हम यहां हैं, तो स्वत: मुक्केबाजी idempotent है। मैंने महसूस किया कि उन्होंने वास्तव में इसे लैंड किए बिना मछली को झुकाया और खेला था।

संबंधित मुद्दे

 संबंधित मुद्दे