2009-08-31 11 views

उत्तर

15

वहाँ है कोई अंतर्निहित एक कॉलर्स बांधने के लिए रास्ते में 1.8.एक्स या 1.9.एक्स में रूबी में आईएनजी।

आप काम करने के लिए https://github.com/banister/binding_of_caller का उपयोग कर सकते हैं।

एमआरआई 2.0 में आप RubyVM :: DebugInspector उपयोग कर सकते हैं, देखें: https://github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb

कार्य नमूना एमआरआई 2.0 में:

require 'debug_inspector' 

def bar(symbol) 
    RubyVM::DebugInspector.open do |inspector| 
    val = eval(symbol.to_s, inspector.frame_binding(2)) 
    puts "#{symbol}: #{val}" 
    end 
end 

def foo 
    a = 100 
    bar(:a) 
end 

foo 
# a: 100 
+0

यहां ऐसा करने के लिए set_trace_func का उपयोग करने के नाजुक तरीके का एक उदाहरण है: http://stackoverflow.com/questions/1314592/how-can-i-get-the-binding-from-methodmissing/1315612#1315612 – rampion

+2

अस्वीकरण शामिल करना चाहिए : कृपया तब तक ऐसा न करें जब तक कि आप * वास्तव में * किसी प्रकार के डिबगिंग के लिए इसका उपयोग नहीं कर रहे हों। – tmandry

3

चेक लेख Variable Bindings in Ruby

class Reference 
    def initialize(var_name, vars) 
    @getter = eval "lambda { #{var_name} }", vars 
    @setter = eval "lambda { |v| #{var_name} = v }", vars 
    end 
    def value 
    @getter.call 
    end 
    def value=(new_value) 
    @setter.call(new_value) 
    end 
end 

def ref(&block) 
    Reference.new(block.call, block.binding) 
end 

def bar(ref) 
    # magic code goes here, it outputs "a = 100" 
    p ref.value 
end 

def foo 
    a = 100 
    bar(ref{:a}) 
end 

foo 
+0

+1 बहुत दिलचस्प लग रहा है , मुझे आश्चर्य है कि यह ब्लॉक के बिना किया जा सकता है हालांकि ... –

+0

मुझे नहीं लगता कि यह रूबी 1.8 में ब्लॉक के बिना किया जा सकता है। एक्स। मैं रूबी 1.9.एक्स से परिचित नहीं हूं, इसलिए चीजें अलग-अलग हो सकती हैं। – neoneye

+0

रूबी 2.1 में आपको अभी भी ब्लॉक की आवश्यकता है, लेकिन 'संदर्भ' के कार्यान्वयन को कॉल का उपयोग करके फिर से किया जा सकता है ['बाध्यकारी # local_variable_get'] (http://www.ruby-doc.org/core-2.1.0/ बाइंडिंग। एचटीएमएल # विधि-i-local_variable_get) और ['बाध्यकारी # vars.local_variable_set'] (http://www.ruby-doc.org/core-2.1.0/Binding.html#method-i-local_variable_set)। हालांकि, वर्तमान कार्यान्वयन संभवतः स्थानीय चर के अलावा पाठक और लेखक विधियों को कॉल करने की अनुमति देता है, जबकि नया कार्यान्वयन नहीं होगा ... – Ajedi32

17

आप foo के संदर्भ bar को पारित करने के लिए है:

def foo 
    a = 100 
    bar(:a, binding) 
end 
def bar(sym, b) 
    puts "#{sym} is #{eval(sym.to_s, b)}" 
end 
+3

@ फ़ोटानस, ओह नहीं। आप देखेंगे कि मेरे उत्तर की तारीख 3.5 साल तक रूबी 2 की भविष्यवाणी करती है। –

+0

क्षमा करें, आप सही हैं। – fotanus

6

बस FYI करें, यहाँ एक "hacky तरीका है।" यह मेरा (पुनः) प्रसिद्ध ppp.rb के कार्यान्वयन है:।

#!/usr/bin/ruby 
# 
# better ppp.rb 
# 

require 'continuation' if RUBY_VERSION >= '1.9.0' 

def ppp(*sym) 
    cc = nil 
    ok = false 

    set_trace_func lambda {|event, file, lineno, id, binding, klass| 
    if ok 
     set_trace_func nil 
     cc.call(binding) 
    else 
     ok = event == "return" 
    end 
    } 
    return unless bb = callcc{|c| cc = c; nil } 

    sym.map{|s| v = eval(s.to_s, bb); puts "#{s.inspect} = #{v}"; v } 
end 

a = 1 
s = "hello" 
ppp :a, :s 

exit 0 

यह वर्तमान में 1.9 के साथ विफल [012] रूबी के set_trace_func में एक बग के कारण।

+0

बहुत रोचक! मैंने इसे [कॉलर_बाइंडिंग का अपना संस्करण] बनाने के लिए अनुकूलित किया है (http://rubychallenger.blogspot.com/2011/07/caller-binding.html)। लेकिन [पीपीपी क्या है?] (Http://stackoverflow.com/questions/6884122/ruby-what-is-ppp-rb) –

7

यहाँ एक आसान वाक्य रचना हैक है, एक बाध्यकारी ब्लॉक में पारित का उपयोग कर:

def loginfo &block 
    what = yield.to_s 
    evaled = eval(what, block.binding) 
    Rails.logger.info "#{what} = #{evaled.inspect}" 
    end 

इस तरह कहा जाता है:

x = 1 
    loginfo{ :x } 

लॉग आउट कर देगा:

x = 1 
+1

FYI ने मेरा उत्तर अपडेट किया –

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

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