दिलचस्प पोस्ट
नेविगेशन पट्टी प्रोग्रामिंग आईओएस जोड़ना php pdo: एक तालिका का स्तंभ नाम प्राप्त करें गर्तिका के संचालन के लिए एक समय समाप्ति सेट करना आईओएस: दो तिथियों की तुलना करें mysql – तारीख की तारीख सीमाओं में दर्ज करें अगर तिथियां मौजूदा लोगों के साथ ओवरलैप नहीं करती हैं क्या कोई फजी खोज या स्ट्रिंग समानता फ़ंक्शन लाइब्रेरीज़ सी # के लिए लिखी गई हैं? Mysql रिकर्सिव का चयन करें सभी स्तर के साथ सभी बच्चे प्राप्त करें गैर-प्रॉपर्टी-सूची वस्तु को एक NSUserDefaults के रूप में सेट करने का प्रयास आईओएस में पैन और स्वाइप के बीच अंतर क्या है? तत्व को किसी अन्य तत्व में कैसे स्थानांतरित करना है? मैं कैसे पायथन के साथ सुंदर प्रिंट ASCII तालिकाओं कर सकते हैं? कब और क्यों प्रतिनिधियों का उपयोग करें? सीमा के साथ GROUP_CONCAT क्या यह संभव है कि रेगेक्स मेटाचैक्टर्स से एसएएल के साथ मज़बूती से बचें उत्पादन में इकाई फ़्रेमवर्क (कोड पहले) माइग्रेशन का उपयोग करना

गतिशील रूप से एक स्थानीय चर बनाने के लिए कैसे?

मेरे पास एक variable var = "some_name" और मैं एक नया ऑब्जेक्ट बनाना चाहूंगा और इसे some_name आवंटित करना some_name । मैं यह कैसे कर सकता हूं? उदाहरण के लिए

 var = "some_name" some_name = Struct.new(:name) # I need this a = some_name.new('blah') # so that I can do this. 

वेब के समाधान से एकत्रित समाधान "गतिशील रूप से एक स्थानीय चर बनाने के लिए कैसे?"

आप गतिशील रूप से रूबी 1.9+ में स्थानीय चर को नहीं बना सकते (आप Eval द्वारा रूबी 1.8 में कर सकते हैं):

 eval 'foo = "bar"' foo # NameError: undefined local variable or method `foo' for main:Object 

उनका उपयोग eval-ed कोड के भीतर ही किया जा सकता है, हालांकि:

 eval 'foo = "bar"; foo + "baz"' #=> "barbaz" 

रूबी 2.1 ने local_variable_set जोड़ा है, लेकिन वह नए स्थानीय चर को नहीं बना सकते हैं:

 binding.local_variable_set :foo, 'bar' foo # NameError: undefined local variable or method `foo' for main:Object 

रूबी खुद को संशोधित किए बिना इस व्यवहार को बदला नहीं जा सकता। वैकल्पिक रूप से इसके बजाय अपने डेटा को अन्य डेटा संरचना में संग्रहीत करने का विचार करना है, जैसे कि कई स्थानीय चर के बजाय एक हैश;

 hash = {} hash[:my_var] = :foo 

ध्यान दें कि दोनों eval और local_variable_set मौजूदा स्थानीय चर को पुन: असाइन करने की अनुमति देते हैं:

 foo = nil eval 'foo = "bar"' foo #=> "bar" binding.local_variable_set :foo, 'baz' foo #=> "baz" 

रूबी 2.2.x के बोलते हुए यह सच है कि आप वर्तमान संदर्भ / बाइंडिंग में प्रोग्रामिक रूप से स्थानीय चर नहीं बना सकते हैं .. लेकिन आप किसी विशेष बाध्यकारी में चर को सेट कर सकते हैं,

 b = binding b.local_variable_set :gaga, 5 b.eval "gaga" => 5 

यहां दिलचस्प बात यह है कि बाध्यकारी होने के लिए हर समय आपको एक नई बाध्यकारी दी जाती है तो आपको वांछित वैरिएबल्स सेट होने पर बाध्यकारी की एक संभाल प्राप्त करने की आवश्यकता है और उसके बाद उसके संदर्भ में eval की आवश्यकता होगी।

यह कैसे उपयोगी है? उदाहरण के लिए, मैं ईआरबी का मूल्यांकन करना चाहता हूं और ईआरबी लिखना बहुत अच्छा है यदि आप <%= opts[:myvar] %> या ऐसा कुछ के बजाय <%= myvar %> उपयोग कर सकते हैं

एक नया बाध्यकारी बनाने के लिए मैं एक मॉड्यूल क्लास विधि का उपयोग कर रहा हूं (मुझे यकीन है कि किसी को सही तरीके से कॉल करने के लिए मुझे सही होगा, जावा में मैं उसे एक स्थिर विधि कहूँगा) विशिष्ट चर के साथ एक स्वच्छ बंधन प्राप्त करने के लिए:

 module M def self.clean_binding binding end def self.binding_from_hash(**vars) b = self.clean_binding vars.each do |k, v| b.local_variable_set k.to_sym, v end return b end end my_nice_binding = M.binding_from_hash(a: 5, **other_opts) 

अब आपके पास वांछित वैरिएबल के साथ बाध्यकारी है। आप इसे ईआरबी या अन्य (संभावित तीसरे पक्ष) विश्वसनीय कोड के अच्छे नियंत्रित मूल्यांकन के लिए उपयोग कर सकते हैं (यह किसी भी तरह का एक सैंडबॉक्स नहीं है)। यह एक अंतरफलक को परिभाषित करने की तरह है

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

 module MyRooTModule class Work def my_instance_method ... end def not_so_clean_binding binding end end class SomeOtherClass end end 

अब मेरे my_object.not_so_clean_binding कोड को #my_instance_method को my_object ऑब्जेक्ट पर कॉल करने की अनुमति देगा। उसी तरह, आप MyRootModule::SomeOtherClass.new बजाय इस बाइंडिंग का उपयोग कर कोड में SomeOtherClass.new उदाहरण के लिए कॉल कर सकते हैं। इसलिए स्थानीय वैरिएबल की तुलना में बाध्यकारी बनाने के दौरान कभी-कभी अधिक विचार की आवश्यकता होती है। HTH

यद्यपि, जैसा कि दूसरों ने बताया है, आप रूबी में स्थानीय वैरिएबल को गतिशील रूप से नहीं बना सकते हैं, तो आप इस व्यवहार को तरीकों से कुछ डिग्री तक अनुकरण कर सकते हैं:

 hash_of_variables = {var1: "Value 1", var2: "Value 2"} hash_of_variables.each do |var, val| define_method(var) do instance_variable_get("@__#{var}") end instance_variable_set("@__#{var}", val) end puts var1 puts var2 var1 = var2.upcase puts var1 

प्रिंटों:

 Value 1 Value 2 VALUE 2 

कुछ पुस्तकालयों को इस तकनीक को उदाहरण_एक्सएसी के साथ एक ब्लॉक में स्थानीय चर के रूप में प्रदर्शित करने के instance_exec गठबंधन करना है:

 def with_vars(vars_hash, &block) scope = Object.new vars_hash.each do |var, val| scope.send(:define_singleton_method, var) do scope.instance_variable_get("@__#{var}") end scope.instance_variable_set("@__#{var}", val) end scope.instance_exec(&block) end with_vars(a: 1, b:2) do puts a + b end 

प्रिंट: 3

ध्यान रखें कि अमूर्त का कोई मतलब बिल्कुल नहीं है:

 with_vars(a: 1, b:2) do a = a + 1 puts a end 

में परिणाम: undefined method `+' for nil:NilClass । इसका कारण यह है कि a= एक वास्तविक स्थानीय चर को परिभाषित करता है, nil आरंभ किया जाता है, जो कि विधि के ऊपर पूर्वता लेता है। फिर a.+(1) को बुलाया जाता है, और nil कोई विधि नहीं होती है, इसलिए एक त्रुटि फेंक दी जाती है।

इसलिए जब यह विधि केवल पढ़ने के लिए स्थानीय चर का अनुकरण करने के लिए बहुत उपयोगी है, यह हमेशा अच्छी तरह से काम नहीं करता है जब आप ब्लॉक के भीतर चर को पुनः असाइन करने का प्रयास करते हैं।

यह सच है कि दूसरों ने क्या लिखा है कि आप किसी स्थानीय संदर्भ में गतिशील रूप से सच वैरिएबल घोषित नहीं कर सकते। हालांकि आप ऑब्जेक्ट एट्रिब्यूट्स के साथ इसी तरह की कार्यक्षमता प्राप्त कर सकते हैं और रूबी वर्ल्ड में सब कुछ एक ऑब्जेक्ट (यहां तक ​​कि मुख्य प्रसंग) है, इसलिए आप उन ऑब्जेक्ट्स को नई एट्रिब्यूट्स के साथ आसानी से बढ़ा सकते हैं। निषिद्ध, यह ऑपरेशन गतिशील रूप से किया जा सकता है आइए इस दृष्टिकोण की जांच करें।

सबसे पहले, irb साथ मुख्य अवसर देखें।

 > self => main > self.class => Object > self.class.ancestors => [Object, Kernel, BasicObject] 

जैसा कि आप अब देख सकते हैं, main वास्तव में एक वस्तु है ऑब्जेक्ट में ऐसे गुण हो सकते हैं, जिनके पास समान अवरोधन संपत्ति चर के रूप में होती है। आम तौर पर, नए वर्ग की घोषणा करते समय हम attr_accessor विधि का प्रयोग करेंगे लेकिन main पहले से एक तत्काल वस्तु है इसलिए हम नई विशेषताओं को सीधे नहीं घोषित कर सकते हैं। यहां मॉड्यूल मिक्सिन बचाव के लिए आते हैं।

 variable_name = 'foo' variable_value = 'bar' variable_module = Module.new do attr_accessor variable_name.to_sym end include variable_module instance_variable_set("@#{variable_name}", variable_value) p foo # "bar" self.foo = 'bad' p foo # "baz" self.class.ancestors # [Object, #<Module:0x007f86cc073aa0>, Kernel, BasicObject] 

अब आप देखते हैं कि main ऑब्जेक्ट नए मॉड्यूल के साथ दागदार था जो कि नए एट्रिब्यूट foo पेश किया था। आगे निरीक्षण के लिए आप देख सकते हैं कि main तरीके अब दो और तरीकों foo और foo=

इस ऑपरेशन को सरल बनाने के लिए मैंने मेटासा मणि लिखा था, जो मैं आपको बेहद उत्साहित करता हूं। यह इसका उपयोग करने का उदाहरण है

 require 'metaxa' include Metaxa introduce :foo, with_value: 'foo' puts foo == 'foo' # true puts foo === get(:foo) # true set :foo, 'foobar' puts foo == 'foobar' # true puts foo === get(:foo) # true self.foo = 'foobarbaz' puts foo == 'foobarbaz' # true puts foo === get(:foo) # true