2014-07-02 4 views
8

मान लीजिए मैं इस जैसे एक वर्ग है:एक curried proc example_eval संभव है?

class Test 
    def test_func 
    140 
    end 
end 

और एक proc, Test से एक सदस्य समारोह का संदर्भ जो:

p = ->(x, y) { x + y + test_func } # => #<Proc:[email protected](pry):6 (lambda)> 

p फोन के लिए, मैं Test का एक उदाहरण के लिए यह बाँध:

test = Test.new      # => #<Test:0x007fb3143c5a68> 
test.instance_exec(1, 2, &p)  # => 143 

अब मान लीजिए कि मैं सिर्फ yको भेजना चाहते हैं, और हमेशा x = 1 पारित:

curried = p.curry[1]    # => #<Proc:0x007fb3142be070 (lambda)> 

आदर्श रूप में मैं सिर्फ instance_exec के रूप में पहले में सक्षम होना चाहिए, लेकिन इसके बजाय:

test.instance_exec(2, &curried) 

=> NameError: undefined local variable or method `test_func' for main:Object 

proc क्या गलत बाध्यकारी हो रहा है में चलता है। क्या देता है?

+1

अच्छी तरह से ऐसा लगता है कि फ़ंक्शन को घुमाने में यह 'test_func' चर को बाध्य करता है जो स्थानीय' test_func' है। मैं यह सोचने की कोशिश कर रहा हूं कि यह क्यों होना चाहिए और कुछ भी नहीं आ सकता है, यहां तक ​​कि चारों ओर खेलना मुझे अपेक्षित परिणाम प्राप्त करने का कोई तरीका नहीं मिल सकता है (एक घुमावदार प्रो पर सही ढंग से बाध्य 'test_func')। अच्छा प्रश्न। –

+2

हाँ यह एक दिलचस्प है। ऐसा लगता है कि प्रो को घुमाने के बाद यह मुख्य रूप से दायरे को बांधता है और परीक्षण के भीतर इसे मूल्यांकन करने के बावजूद यह मुख्य रूप से स्कॉइंग को बनाए रखता है। – jvans

+0

मैंने इसे एक बग के रूप में बताया [यहां] (https: //bugs.ruby-lang।संगठन/मुद्दे/10006), हम देखेंगे कि वास्तव में यह है या यदि कोई वहां समझा सकता है। –

उत्तर

3

हाँ, मुझे विश्वास है कि यह एक बग है।

मुझे लगता है कि यह इस तथ्य के नीचे आता है कि curry एक सामान्य प्रो के बजाय "सी स्तर proc" देता है। मैं दोनों के बीच का अंतर पूरी तरह से समझ नहीं पा रहा हूं (मुझे लगता है कि पूर्व में रूबी सी कोड द्वारा बनाया गया एक है जो curry करता है), लेकिन आप बता सकते हैं कि जब आप कोशिश करते हैं और बाध्यकारी करते हैं तो वे अलग होते हैं।

p.binding # => #<Binding:0x000000020b4238> 
curried.binding # => ArgumentError: Can't create a binding from C level Proc 

the source को देख कर, यह लग रहा है अपने आंतरिक struct अभ्यावेदन की तरह iseq सदस्य, जो कहते हैं अनुदेश अनुक्रम की किस तरह इस ब्लॉक रखती है के लिए अलग-अलग मान।

यह है जब आप instance_exec फोन, अंत में vm.c में invoke_block_from_c बुला, जो iseq प्रकार के आधार पर शाखाओं समाप्त होता है जो महत्वपूर्ण है:

else if (BUILTIN_TYPE(block->iseq) != T_NODE) { 
    ... 
} else { 
    return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr); 
} 

शाखा मैं बाहर याद किया (...) के साथ vm_push_frame बुला समाप्त होता है क्या कुछ पर्यावरण की तरह दिखता है जहां vm_yield_with_cfunc नहीं है।

तो मेरा अनुमान यह होगा कि करीबी प्रो सी कोड में बनाई गई है और आपकी पहली proc की तुलना में एक अलग 'प्रकार' से समाप्त होती है, दूसरी शाखा उपरोक्त स्निपेट में ली जाती है और enviornment का उपयोग नहीं किया जाता है।

मैं कहना चाहिए कि यह सब कोड, मैं किसी भी परीक्षण या करने की कोशिश की कुछ भी रन आउट नहीं किया है पढ़ने के आधार पर सुंदर काल्पनिक है (और मैं भी सभी कि आंतरिक रूबी से परिचित वैसे भी नहीं हूँ !)

+0

अच्छा खोज - मैंने सी कोड में भी चारों ओर पोक किया लेकिन उसे पकड़ नहीं लिया! –

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