रूबी कॉन्स: प्रतीकों की सूची को स्ट्रिंग्स में क्यों बदलें


85

मैं रूबी Koans https://github.com/edgecase/ruby_koans/blob/master/src/about_symbols.rb##2626 में इस परीक्षण का जिक्र कर रहा हूं।

def test_method_names_become_symbols
  symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }
  assert_equal true, symbols_as_strings.include?("test_method_names_become_symbols")
end


  # THINK ABOUT IT:
  #
  # Why do we convert the list of symbols to strings and then compare
  # against the string value rather than against symbols?

हमें वास्तव में पहले उस सूची को तार में क्यों बदलना है?

जवाबों:


110

यह कैसे प्रतीकों काम के साथ क्या करना है। प्रत्येक प्रतीक के लिए, इसका केवल एक ही वास्तव में मौजूद है। पर्दे के पीछे, एक प्रतीक सिर्फ एक संख्या है जिसे एक नाम (एक बृहदान्त्र के साथ शुरू) द्वारा संदर्भित किया जाता है। इस प्रकार, दो प्रतीकों की समानता की तुलना करते समय, आप ऑब्जेक्ट पहचान की तुलना कर रहे हैं कि इस प्रतीक को संदर्भित पहचानकर्ता की सामग्री को।

यदि आप सरल परीक्षण करने के लिए थे : परीक्षण == "परीक्षण" , यह गलत होगा। इसलिए, यदि आप इस तरह से परिभाषित सभी प्रतीकों को एक सरणी में इकट्ठा करना चाहते हैं, तो आपको उनकी तुलना करने से पहले उन्हें स्ट्रिंग में बदलना होगा। आप इसे विपरीत तरीके से नहीं कर सकते हैं (पहले जिस स्ट्रिंग को आप एक प्रतीक में तुलना करना चाहते हैं उसे रूपांतरित करें) क्योंकि ऐसा करने से आप उस प्रतीक के एकल उदाहरण का निर्माण करेंगे और प्रतीक के साथ आपकी सूची को "प्रदूषित" करेंगे जो आप अस्तित्व के लिए परीक्षण कर रहे हैं।

उम्मीद है की वो मदद करदे। यह थोड़ा अजीब है, क्योंकि आपको परीक्षण के दौरान गलती से उस प्रतीक को बनाए बिना एक प्रतीक की उपस्थिति के लिए परीक्षण करना होगा। आप आमतौर पर ऐसा कोड नहीं देखते हैं।


2
ध्यान दें कि इसे सुरक्षित रूप से करने का एक बेहतर तरीका Symbol.all_symbolsएक चर के आउटपुट को असाइन करना है , फिर समावेश के लिए परीक्षण करें। प्रतीक तुलना में तेज हैं, और आप हजारों प्रतीकों को तार में बदलने से बच रहे हैं।
कोरीवर्ड

4
यह अभी भी प्रतीक बनाने की समस्या है जिसे नष्ट नहीं किया जा सकता है। उस प्रतीक के भविष्य के किसी भी परीक्षण को बर्बाद कर दिया जाएगा। लेकिन यह सिर्फ एक Koan है, यह बहुत मतलब नहीं है या तेज हो, बस कैसे प्रतीकों काम करते हैं।
AboutRuby

2
यह जवाब मेरे लिए काम नहीं करता है। यदि हम एक प्रतीक के अस्तित्व की खोज कर रहे हैं, तो हम एक स्ट्रिंग तर्क क्यों निर्दिष्ट कर रहे हैं include?यदि हम निर्दिष्ट :test_method_names_become_symbolsकरते हैं कि हमें उन सभी प्रतीकों को तार में बदलना नहीं होगा।
आइजैक राबिनोविच

3
इसहाक, पहचाने गए मुद्दे के कारण, जो यह है कि :test_method_names_become_symbolsतुलना में निर्दिष्ट करने से यह पैदा होगा, इसलिए तुलना हमेशा सच होगी। all_symbolsस्ट्रिंग्स में कनवर्ट करके और स्ट्रिंग्स की तुलना करके, हम यह पहचान सकते हैं कि क्या प्रतीक तुलना से पहले मौजूद था।
स्टीफन

3
इतना मैं नहीं समझता। अगर मैं >> array_of_symbols = Symbol.all_symbols करता हूं, तो >> array_of_symbols.include? (: Not_yet_used), मैं गलत हो जाता हूं, और मैं कुछ ऐसी चीजों से सच हो जाता हूं जो परिभाषित थी, इसलिए मुझे समझ नहीं आ रहा है कि स्ट्रिंग्स में रूपांतरण क्यों है? ।
कोडेनोबो

75

क्योंकि अगर तुम करते हो:

assert_equal true, all_symbols.include?(:test_method_names_become_symbols)

यह (आपके रूबी कार्यान्वयन के आधार पर) स्वचालित रूप से सच हो सकता है, क्योंकि :test_method_names_become_symbolsप्रतीक बनाता है। इस बग रिपोर्ट देखें ।


1
तो स्वीकृत उत्तर गलत है (या ऐसा मुझे लगता है)।
आइजैक राबिनोविच

3
इसहाक, अन्य उत्तर गलत नहीं है, लेकिन इसे स्पष्ट रूप से समझाया नहीं गया है। पक्का। वैसे भी, आप निम्न के साथ एंड्रयू के क्या कह रहे हैं सत्यापित कर सकते हैं: assert_equal true, Symbol.all_symbols.include? (: Abcdef) यह हमेशा प्रतीक की परवाह किए बिना (कम से कम, यह मेरे लिए) गुजर जाएगा। मुझे लगता है कि एक पाठ है, बूलियन ध्वज के रूप में प्रतीकों की उपस्थिति / अनुपस्थिति का उपयोग करने की कोशिश न करें।
स्टीफन

1
इस सवाल को देखते हुए, जो अभी भी मुझे दिलचस्पी देता है, 2 साल बाद, मैं वास्तव में इस जवाब, और टिप्पणियों की सराहना करता हूं। मुझे लगता है कि इसहाक सही है यह सबसे स्पष्ट रूप से व्याख्या करने वाला उत्तर है कि तार के लिए रूपांतरण क्यों हो सकता है, हालांकि मुझे लगता है कि आप मध्यस्थ काम (तुलना से पहले सभी प्रतीकों को स्टोर कर सकते हैं) कर सकते हैं ताकि यह बेहतर काम कर सके।
कोडेनोबोब

3

ऊपर दोनों उत्तर सही हैं, लेकिन मैं इसके बाद के संस्करण कार्तिक के सवाल के आलोक में मैं एक परीक्षण दिखाता है कि कैसे एक सही ढंग से करने के लिए एक प्रतीक के पारित हो सकता है पोस्ट होगा सोचा includeविधि

def test_you_create_a_new_symbol_in_the_test
  array_of_symbols = []
  array_of_symbols << Symbol.all_symbols
  all_symbols = Symbol.all_symbols.map {|x| x}
  assert_equal false, array_of_symbols.include?(:this_should_not_be_in_the_symbols_collection)  #this works because we stored all symbols in an array before creating the symbol :this_should_not_be_in_the_symbols_collection in the test
  assert_equal true, all_symbols.include?(:this_also_should_not_be_in_the_symbols_collection) #This is the case noted in previous answers...here we've created a new symbol (:this_also_should_not_be_in_the_symbols_collection) in the test and then mapped all the symbols for comparison. Since we created the symbol before querying all_symbols, this test passes.
end

Koans के बारे में एक अतिरिक्त ध्यान दें: putsयदि आप कुछ भी नहीं समझते हैं तो कथनों के साथ-साथ कस्टम परीक्षणों का भी उपयोग करें। उदाहरण के लिए, यदि आप देखें:

string = "the:rain:in:spain"
words = string.split(/:/)

और पता नहीं क्या wordsहो सकता है, लाइन जोड़ें

puts words

और rakeकमांड लाइन पर चलते हैं । इसी तरह, जो मैंने ऊपर जोड़ा है वह परीक्षण रूबी की कुछ बारीकियों को समझने के संदर्भ में सहायक हो सकता है।


इस सवाल को देखते हुए, जो अभी भी मुझे दिलचस्पी देता है, 2 साल बाद, मैं वास्तव में इस जवाब, और टिप्पणियों की सराहना करता हूं।
कोडेनोबोब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.