2010-02-08 16 views
16

जब आज कुछ rspec लेखन, मैं की तुलना की तारीख (और समय) नहीं के बराबर करने के लिए उदाहरणों के साथ कुछ अनपेक्षित व्यवहार बारे में जाना।रूबी में, शून्य के साथ समानता क्यों होती है ("Date.new == nil") शून्य वापस आती है?

[email protected] ~ $ ruby -v 
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0] 
[email protected] ~ $ irb 
>> 1 == nil 
=> false 
>> "string" == nil 
=> false 
>> :sym == nil 
=> false 
>> false == nil 
=> false 
>> [] == nil 
=> false 
>> {} == nil 
=> false 
>> Proc.new {} == nil 
=> false 

अब तक तो अच्छा है, है ना: यहाँ कच्चे माणिक (कोई रेल या अन्य पुस्तकालयों) का उपयोग कर एक नमूना है?

>> Date.new === nil 
=> false 

वहाँ क्यों ऐसा होता है या क्यों इस व्यवहार वांछित है के रूप में किसी भी स्पष्टीकरण है:

>> Date.new == nil 
=> nil 
>> Time.new == nil 
=> nil 

तिथि का अपना === है, जो ठीक काम करता है को लागू करता है? == तुलनात्मक रूप से लागू किया गया प्रतीत होता है। ==, हालांकि उस पर दस्तावेज़ीकरण से कोई संकेत नहीं दिया गया है कि यह कभी भी शून्य नहीं होगा। इसका डिजाइन निर्णय क्या है?

अद्यतन! इस 1.9.2 में ऐसा नहीं है:

$ irb 
ruby-1.9.2-p136 :001 > require 'date' 
=> true 
ruby-1.9.2-p136 :002 > Date.new == nil 
=> false 
ruby-1.9.2-p136 :003 > Time.new == nil 
=> false 

उत्तर

12

मैं स्रोत की जाँच की और यहाँ मैं क्या पता चला है:

तुलना ऑपरेटर सभी तुलनीय द्वारा परिभाषित <=> के साथ एक साथ समारोह rb_cmpint का उपयोग करें। rb_cmpint अपवाद उठाता है जब एक ऑपरेंड शून्य है।

तो तुलनीय उठाने के ऑपरेटरों एक अपवाद है, तो आरएचएस एलएचएस करने के लिए तुलनीय नहीं है। अर्थात। 5 < 2 गलत है, लेकिन 5 < "la" एक अपवाद उठाता है। वे ऐसा मामलों के बीच अंतर करने के लिए करते हैं जहां < सत्य नहीं है क्योंकि rhs छोटा है और ऐसे मामले जहां यह सत्य नहीं है क्योंकि rhs तुलनीय नहीं है। या दूसरे शब्दों में: जब x < y गलत है संकेत मिलता है कि कि x >= y सच है। तो ऐसे मामलों में जहां यह मामला नहीं होगा, यह एक अपवाद फेंकता है।

== अपवाद उठाना बुरा होगा, क्योंकि == आमतौर पर (और नहीं) को अपने ऑपरेटरों को तुलनीय होने की आवश्यकता नहीं होती है। हालांकि == अन्य ऑपरेटरों के समान विधि का उपयोग करता है, जो अपवाद उठाता है। तो पूरा फ़ंक्शन बस rb_rescue में लपेटा गया है। और यदि कोई अपवाद फेंक दिया जाता है तो nil लौटाता है।

ध्यान दें कि यह केवल 1.8 रूबी के लिए लागू होता है। इसे 1.9 में तय किया गया है और अब == कभी भी nil नहीं लौटाता है (बेशक यदि आप अपना == परिभाषित करते हैं तो)।

+1

Fwiw, 1.8.7 (और possibily पहले) तुलना उदाहरण आप दे दी है में ArgumentError को जन्म देती है: >> 5 < "ला" ArgumentError: स्ट्रिंग के साथ Fixnum की तुलना में विफल रहा है (आईआरबी) से \t: 41: में '<' \t से (irb): 41 हालांकि, आपकी व्याख्या समझ में आती है, और ऐसा लगता है कि दिनांक # <=> को कभी भी अपडेट नहीं किया गया था (उद्देश्य पर? कौन जानता है!) वापसी के बदले उठाने के लिए। मुझे लगता है कि मेरा मुख्य गोमांस अब सभी (आमतौर पर) रूबी डॉक्स के साथ है जो इस व्यवहार का उल्लेख नहीं करते हैं: * http://ruby-doc.org/core/classes/Date.html#M000673 * http://ruby-doc.org/core/classes/Comparable.html –

+0

(पृष्ठ पर 'शून्य' का कोई जिक्र नहीं) यहां आया क्योंकि मैं के माध्यम से [रूबी koans] (http मेरे रास्ते काम कर रहा हूँ: // rubykoans। com /) है, जो सवाल में शामिल हैं "यह बेहतर obj.nil उपयोग करने के लिए obj == शून्य # क्यों है? या?" मुझे उम्मीद है कि "शून्य" से बेहतर जवाब है क्योंकि यह कम छोटी है "। –

4

दिनांक वर्ग Comparable#== विधि भी शामिल है, लेकिन यह है कि विधि रिसीवर के <=> विधि invokes। इस मामले में यह Date#<=> है, जो किसी अन्य दिनांक वस्तु की अपेक्षा करता है। जब यह nil प्राप्त करता है तो यह nil देता है। यह व्यवहार निश्चित रूप से असंगत लगता है, और मैं इसके पीछे कारणों को नहीं जानता।

7

आप कोड के लिए इस पर निर्भर करता है कर रहे हैं, तो आप हमेशा .nil उपयोग कर सकते हैं? विधि जो किसी भी रूबी ऑब्जेक्ट का जवाब देती है।

>> Date.new.nil? 
=> false 
+1

व्यक्तिगत रूप से, यह पढ़ पर, मैं कभी उपयोग करने के लिए '== शून्य' फिर से जा रहा हूँ! – Shadowfirebird

0

यह होता है क्योंकि आप चीजें हैं जो परिभाषित नहीं कर रहे हैं की तुलना नहीं कर सकते हैं। यह वांछनीय है क्योंकि यदि आपके कम से कम एक ऑपरेटर को परिभाषित नहीं किया गया है तो आप परिणाम के बारे में कोई निष्कर्ष नहीं निकाल सकते हैं, जो सच बोलने से अलग है।

भाषाओं का एक बहुत नहीं के बराबर और झूठे ही इलाज है, जो संदिग्ध सुविधा के लिए विशुद्ध रूप से है। यह निश्चित रूप से गणितीय सही नहीं है।

+1

तो इस कारण थे, तो यह केवल लागू होते हैं जब शून्य के साथ तुलना करेंगे। बात वह नहीं है। आप तो उदाहरण के लिए Date.new == [1,2,3] शून्य (1.9 जहां == कभी नहीं के बराबर रिटर्न को छोड़कर) देता है और साथ ही, जब आप कुछ भी खिलाफ एक तुलनीय उद्देश्य यह है कि एक ही प्रकार की नहीं है की तुलना नहीं के बराबर मिलता है । – sepp2k

+0

अच्छा बिंदु। कैसे "ऐसा होता है क्योंकि आप अलग-अलग प्रकार की दो वस्तुओं की तुलना नहीं कर सकते हैं, इसका एक सबसेट शून्य के साथ तुलनात्मक है।" :) ओपी ने पूछा कि आप नील के साथ तुलना क्यों नहीं कर सकते हैं, और मेरा मानना ​​है कि मेरा जवाब उस संदर्भ में सही है; हालांकि, यह पूरा कारण नहीं है। – Duncan

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