2013-03-26 6 views
8

मैं एक चर नाम कैसे प्राप्त कर सकता हूं? उदाहरण के लिए,रूबी: परिवर्तनीय नाम प्राप्त करना

def get_var_name(var) 
    # return variable name 
end 

myname = nil 
get_var_name myname #=> myname 

प्रारंभिक उद्देश्य:

somevar = "value" 

puti somevar #=> somevar = "value" 
# that is a shortage for 
# `puts "somevar = #{somevar.inspect}"` 

मेरे कोशिश:

def puti(symb) 
    var_name = symb.to_s 
    var_value = eval(var_name) 
    puts "#{var_name} = #{var_value.inspect}" 
end 
puti :@somevar # that actually will work only with class vars or whatever considering var scope; 
+0

http://stackoverflow.com/questions/1356749 यह आपकी आवश्यकता के करीब है। –

उत्तर

2

सबसे पहले, आप puti को लागू नहीं कर सकते हैं और आउटपुट a_var = value of a_var के रूप में आउटपुट प्राप्त करने के लिए सीधे puti a_var पर कॉल कर सकते हैं। puti के शरीर पर, रूबी केवल puti के औपचारिक पैरामीटर नाम देखता है, यह वास्तविक पैरामीटर नामों का अनुमान नहीं लगा सकता है।

सी/सी ++ जैसी किसी अन्य भाषा में, आप puti को लागू करने के लिए Macro का उपयोग कर सकते हैं। यह एक और कहानी है।

हालांकि, आप Continuation की सहायता से put :a_var लागू कर सकते हैं। एक अन्य प्रश्न में "Can you eval code in the context of a caller in Ruby?", Sony Santos ने कॉलर के बाध्यकारी (पर्ल कॉलर फ़ंक्शन की तरह कुछ) प्राप्त करने के लिए caller_binding कार्यान्वयन प्रदान किया है।

कार्यान्वयन को थोड़ा सा बदला जाना चाहिए, क्योंकि callcc ब्लॉक की वापसी मूल्य को पहली बार लौटता है। तो आपको nil की बजाय Continuation का एक उदाहरण मिलेगा। यहाँ अद्यतन संस्करण है:

require 'continuation' if RUBY_VERSION >= '1.9.0' 

def caller_binding 
    cc = nil  # must be present to work within lambda 
    count = 0 # counter of returns 

    set_trace_func lambda { |event, file, lineno, id, binding, klass| 
    # First return gets to the caller of this method 
    # (which already know its own binding). 
    # Second return gets to the caller of the caller. 
    # That's we want! 
    if count == 2 
     set_trace_func nil 
     # Will return the binding to the callcc below. 
     cc.call binding 
    elsif event == "return" 
     count += 1 
    end 
    } 
    # First time it'll set the cc and return nil to the caller. 
    # So it's important to the caller to return again 
    # if it gets nil, then we get the second return. 
    # Second time it'll return the binding. 
    return callcc { |cont| cc = cont; nil } 
end 

# Example of use: 

def puti *vars 
    return unless bnd = caller_binding 
    vars.each do |s| 
    value = eval s.to_s, bnd 
    puts "#{s} = #{value.inspect}" 
    end 
end 

a = 1 
b = 2 
puti :a, :b 
e = 1 # place holder... 

# => a = 1 
# b = 2 

नोट puti, अपने कार्यक्रम के अंतिम बयान नहीं होना चाहिए अन्यथा रूबी दुभाषिया तुरंत समाप्त कर देगा और पता लगाने समारोह को चलाने के लिए कोई मौका नहीं है। तो यह आखिरी "प्लेस होल्डर" लाइन का मुद्दा है।

+0

यह हैकी है लेकिन मुझे यह पसंद है। धन्यवाद; – ted

8

आप वर्तमान चर गुंजाइश के बंधन है, जो आप the Binding class के साथ क्या भर में ले जाने के लिए की जरूरत है:

def puti(symb, the_binding) 
    var_name = symb.to_s 
    var_value = eval(var_name, the_binding) 
    puts "#{var_name} = #{var_value.inspect}" 
end 

somevar = 3 

puti :somevar, binding # Call the binding() method 

    #=> outputs "somevar = 3" 

binding() विधि एक बाइंडिंग ऑब्जेक्ट देती है जो विधि को उस बिंदु पर संदर्भ को याद करती है जिसे विधि कहा जाता था। फिर आप eval() में बाध्यकारी पास करते हैं, और यह उस संदर्भ में चर का मूल्यांकन करता है।

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