रूबी में रेगेक्स ऑब्जेक्ट को "मिथ्या" क्यों माना जाता है?


16

रूबी "की एक सार्वभौमिक विचार है truthiness " और " falsiness "।

रूबी करता बूलियन वस्तुओं के लिए दो विशिष्ट वर्गों है, TrueClassऔर FalseClass, विशेष चरों से निरूपित किया सिंगलटन उदाहरणों के साथ trueऔर false, क्रमशः।

हालांकि, truthiness और falsiness उन दो वर्गों के उदाहरण तक सीमित नहीं हैं, अवधारणा है सार्वभौमिक और रूबी में हर वस्तु पर लागू होता। प्रत्येक वस्तु या तो सत्य है या मिथ्या है । नियम बहुत सरल हैं। विशेष रूप से, केवल दो वस्तुएं मिथ्या हैं :

  • nil, का एकल उदाहरण NilClassऔर
  • falseका एकल उदाहरण FalseClass

हर एक अन्य वस्तु है truthy । इसमें ऐसी वस्तुएं भी शामिल हैं जिन्हें अन्य प्रोग्रामिंग भाषाओं में गलत माना जाता है , जैसे कि

ये नियम भाषा में निर्मित हैं और उपयोगकर्ता-निश्चित नहीं हैं। कोई to_boolअंतर्निहित रूपांतरण या कुछ भी समान नहीं है।

यहाँ आईएसओ रूबी भाषा विशिष्टता से एक उद्धरण है :

6.6 बूलियन मूल्य

एक वस्तु को एक सत्य वस्तु या एक झूठी वस्तु में वर्गीकृत किया जाता है ।

केवल झूठी और शून्य झूठी वस्तुएं हैं। झूठी कक्षा का एकमात्र उदाहरण है FalseClass(देखें 15.2.6), जिसके लिए झूठी अभिव्यक्ति का मूल्यांकन होता है (देखें 11.5.4.8.3)। नील वर्ग का एकमात्र उदाहरण है NilClass(देखें 15.2.4), जिसके लिए एक नील-अभिव्यक्ति का मूल्यांकन होता है (देखें 11.5.4.8%)।

झूठी और शून्य के अलावा अन्य वस्तुओं को सत्य वस्तुओं में वर्गीकृत किया जाता है। सत्य कक्षा का एकमात्र उदाहरण है TrueClass(देखें 15.2.5), जिसके लिए एक सच्चे-अभिव्यक्ति का मूल्यांकन होता है (देखें 11.5.4.8.3)।

निष्पादन योग्य रूबी / युक्ति से सहमत प्रतीत होता है :

it "considers a non-nil and non-boolean object in expression result as true" do
  if mock('x')
    123
  else
    456
  end.should == 123
end

उन दो स्रोतों के अनुसार, मुझे लगता है कि Regexpएस भी सत्य हैं , लेकिन मेरे परीक्षणों के अनुसार, वे नहीं हैं:

if // then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are falsy'

मैंने इसका परीक्षण YARV 2.7.0-Preview1 , TruffleRuby 19.2.0.1 , और JRuby 9.2.8.0 पर किया । सभी तीन कार्यान्वयन एक दूसरे के साथ सहमत हैं और आईएसओ रूबी भाषा विशिष्टता और रूबी / युक्ति की मेरी व्याख्या से असहमत हैं।

अधिक सटीक रूप से, ऐसी Regexpवस्तुएं जो Regexp शाब्दिक रूप से मूल्यांकन करने का परिणाम होती हैं , मिथ्या होती हैं , जबकि वे Regexpवस्तुएं जो किसी अन्य अभिव्यक्ति का परिणाम हैं, सत्य हैं :

r = //
if r then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are truthy'

यह एक बग, या वांछित व्यवहार है?


दिलचस्प बात यह है कि Regex.new("a")सच्चाई है।
११'१

!!//गलत है लेकिन !!/r/सच है। वास्तव में अजीब।
अधिकतम

@ मैक्स मेरे लिए (आरवीएम) रूबी 2.4.1 का उपयोग !!/r/करता है false
3limin4t0r

माफ़ करना मेरे बुरे @ 3limin4t0r तुम सही हो। मैंने वास्तव में कुछ किया होगा जैसे कि एक प्रशंसा चिह्न छोड़ना।
अधिकतम

2
एक परिकल्पना, मुझे लगता है कि //में if // thenएक परीक्षण (के लिए एक शॉर्टकट के रूप में समझा जाता है if //=~nil thenएक Regexp उदाहरण के रूप में और नहीं (कि हमेशा falsy जो कुछ पैटर्न है))।
कासिमिर एट हिप्पोलाइट

जवाबों:


6

यह एक बग नहीं है। क्या हो रहा है रूबी कोड को फिर से लिख रही है ताकि

if /foo/
  whatever
end

प्रभावी रूप से बन जाता है

if /foo/ =~ $_
  whatever
end

यदि आप एक सामान्य स्क्रिप्ट में इस कोड को चला रहे हैं (और -eविकल्प का उपयोग नहीं कर रहे हैं ) तो आपको एक चेतावनी देखनी चाहिए:

warning: regex literal in condition

यह शायद कुछ समय के लिए भ्रमित करने वाला है, यही वजह है कि चेतावनी दी गई है, लेकिन -eविकल्प का उपयोग करके एक पंक्ति के लिए उपयोगी हो सकता है । उदाहरण के लिए, आप किसी फ़ाइल से दिए गए regexp से मेल खाने वाली सभी पंक्तियों को प्रिंट कर सकते हैं

$ ruby -ne 'print if /foo/' filename

(के लिए डिफ़ॉल्ट तर्क printहै $_के रूप में अच्छी तरह से।)


यह भी देखें -n, -p, -aऔर -lविकल्प है, साथ ही कर्नेल तरीकों में से मुट्ठी भर है कि ही उपलब्ध रहती हैं -nया -pउपयोग किया जाता है ( chomp, chop, gsubऔर sub)।
मैट

उस पार्सर का एक दूसरा भाग भी है जहाँ उस चेतावनी को उत्सर्जित किया जाता है। मैं नहीं जानता कि वहाँ क्या चल रहा है।
मैट

मेरा मानना ​​है कि "दूसरा भाग" वह है जो वास्तव में इस प्रश्न पर लागू होता है। NODE_LITप्रकार के साथ T_REGEXP। आपने अपने उत्तर में जो पोस्ट किया है वह एक डायनामिक Regexpशाब्दिक है , यानी एक Regexpशाब्दिक जो प्रक्षेप का उपयोग करता है, जैसे /#{''}/
Jörg W Mittag

@ JörgWMittag मुझे लगता है कि आप सही हैं। संकलक और उत्पन्न बायोटेक में चारों ओर घूमना, ऐसा लगता है कि डायनेमिक रेगेक्सप के मामले में पार्स ट्री $_को एक नोड के रूप में स्पष्ट रूप से जोड़ने के लिए फिर से लिखा गया है, जो संकलक सामान्य रूप से संभालता है, जबकि स्थैतिक मामले में यह सब निपटा जाता है। संकलक। जो मेरे लिए शर्म की बात है क्योंकि "हे, आप देख सकते हैं कि जहां पार्स पेड़ को फिर से लिखा गया है" एक अच्छा जवाब के लिए बनाता है।
मैट

4

यह (जहाँ तक मैं बता सकता हूँ) माणिक भाषा की एक अनियोजित विशेषता है, जिसका परिणाम यह है :

it "matches against $_ (last input) in a conditional if no explicit matchee provided" do
  -> {
    eval <<-EOR
    $_ = nil
    (true if /foo/).should_not == true
    $_ = "foo"
    (true if /foo/).should == true
    EOR
  }.should complain(/regex literal in condition/)
end

आप आम तौर पर के बारे में सोच सकते हैं $_के रूप में "अंतिम स्ट्रिंग द्वारा पढ़ा gets"

मामलों को और अधिक भ्रामक बनाने के लिए, $_(साथ में $-) एक वैश्विक चर नहीं है; इसका स्थानीय दायरा है


जब एक गहरे लाल रंग का स्क्रिप्ट शुरू होता है, $_ == nil

तो, कोड:

// ? 'Regexps are truthy' : 'Regexps are falsey'

जैसे व्याख्या की जा रही है:

(// =~ nil) ? 'Regexps are truthy' : 'Regexps are falsey'

... जो झूठा लौटाता है।

दूसरी ओर, एक के लिए गैर शाब्दिक regexp (जैसे r = //या Regexp.new('')), यह विशेष व्याख्या लागू नहीं होता।

//सत्य है; इसके अलावा रूबी में अन्य सभी ऑब्जेक्ट की तरह nilऔर false


जब तक कमांड लाइन पर सीधे एक माणिक स्क्रिप्ट नहीं चला जाता है (अर्थात -eध्वज के साथ ), रूबी पार्सर इस तरह के खिलाफ चेतावनी प्रदर्शित करेगा:

चेतावनी: हालत में रेगेक्स शाब्दिक

आप स्क्रिप्ट में इस व्यवहार का उपयोग कर सकते हैं, जैसे कुछ:

puts "Do you want to play again?"
gets
# (user enters e.g. 'Yes' or 'No')
/y/i ? play_again : back_to_menu

... लेकिन इसके परिणाम के लिए स्थानीय चर निर्दिष्ट करना getsऔर इस मूल्य के खिलाफ regex जाँच स्पष्ट रूप से करना सामान्य होगा।

मैं खाली रेक्स के साथ इस चेक को करने के लिए किसी भी उपयोग के मामले से अवगत नहीं हूं , खासकर जब एक शाब्दिक मूल्य के रूप में परिभाषित किया गया हो। परिणाम है कि आप पर प्रकाश डाला गया है वास्तव में सबसे रूबी डेवलपर्स ऑफ-गार्ड पकड़ लेंगे।


मैंने केवल एक उदाहरण के रूप में सशर्त का उपयोग किया। !// #=> trueएक ही व्यवहार है और एक सशर्त में नहीं है। मुझे कोई बूलियन संदर्भ (सशर्त या नहीं) नहीं मिला, जहां यह अपेक्षा के अनुरूप व्यवहार करता है।
जोर्ग डब्ल्यू मित्तग

@ JörgWMittag क्या आपका मतलब उदाहरण के लिए !// ? true : falseरिटर्न है true? मुझे लगता है कि यह फिर से वही बिंदु है - इसकी व्याख्या की जा रही है:!(// =~ nil) ? true : false
टॉम लॉर्ड

यदि आप $_ = 'hello world'उपरोक्त कोड को चलाने से पहले मैन्युअल रूप से सेट करते हैं, तो आपको एक अलग परिणाम प्राप्त करना चाहिए - क्योंकि // =~ 'hello world', लेकिन मेल नहीं खाता nil
टॉम लॉर्ड

नहीं, मेरा मतलब !// बिना सशर्त मूल्यांकन के है true। आपने जिस युक्ति का हवाला दिया है वह Regexpएक सशर्त में शाब्दिक है, लेकिन इस उदाहरण में, कोई शर्त नहीं है, इसलिए यह कल्पना लागू नहीं होती है।
डब्ल्यू पर Jörg W Mittag

2
आह .. हाँ, बहुत हैरानी की बात है। व्यवहार जुड़ा हुआ प्रतीत होता है, यद्यपि: puts !//; $_ = ''; puts !//- मुझे लगता है क्योंकि पार्सर इसे मैक्रो की तरह विस्तारित करता है; यह जरूरी नहीं कि एक सशर्त के अंदर होना चाहिए?
टॉम लॉर्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.