2012-09-19 20 views
7

मैं फ़ंक्शन कॉल की श्रृंखला में get का उपयोग करने का प्रयास कर रहा हूं, लेकिन ऑब्जेक्ट नामों की लुकअप वातावरण को छोड़ने लगती है। उदाहरण के लिए:आर वातावरण और फ़ंक्शन कॉल स्टैक्स

foo <- 1 # variable in .GlobalEnv 

getter <- function(x) {get(x)} 
getter("foo") # returns 1, which is expected 

f1 <- function() { 
    foo <- 2 # local variable in the function scope 
    getter("foo") 
} 

f1() # still returns 1, would've expected to return 2 

ऐसा क्यों है कि फोन करने f1 रिटर्न वैश्विक वातावरण में foo और नहीं बुला समारोह के परिवेश में foo है?

मेरे पास get कॉलिंग फ़ंक्शन के वातावरण में कैसे दिख सकता है? pos = sys.parent() सेट करना प्रतीत नहीं होता है।

उत्तर

6

आप getter निर्धारित करते हैं माता-पिता फ्रेम में देखने के लिए, यह काम करता है:

getter <- function(x) get(x, envir=parent.frame()) 

तब:

getter("foo") 
[1] 1 

f1() 
[1] 2 
+1

ऐसा हुआ, धन्यवाद! यह क्यों है कि parent.frame() काम करता है लेकिन sys.parent() नहीं? क्या कोई ऐसा दस्तावेज है जो चर्चा करता है कि ये सभी अलग-अलग कार्य कैसे काम करते हैं, और संख्या या नाम से पर्यावरण का जिक्र करने के बीच अंतर? – hgcrpd

+2

@hgcrpd 'sys.parent' फ्रेम/पर्यावरण नहीं, एक पूर्णांक देता है। 'parent.frame' फ्रेम प्राप्त करने के लिए' sys.parent' जानकारी के साथ 'sys.parent' जानकारी का उपयोग करता है (न केवल इसके पूर्णांक मान)। –

13

आप फ्रेम और वातावरण के बीच सूक्ष्म अंतर से फिसल किया जा रहा है (जो फ्रेम के वातावरण के बाद भी और अधिक सूक्ष्म, या शायद वातावरण फ्रेम हैं) और lexical and dynamic scoping के बीच का अंतर। सहायता पृष्ठ में parent.frame और अन्य स्थानों पर विभिन्न विवरणों में फैले कुछ विवरण हैं।

कोशिश करते हैं और आसान बनाने के लिए:

आपका getter कार्य है अपने स्वयं के environment जहां कि कार्य करने के लिए स्थानीय चर जमा हो जाती है (x इस मामले में)। चूंकि आर को अक्षय रूप से स्कॉप्ड किया गया है जिसका अर्थ है कि कार्य वातावरण में एक अभिभावक वातावरण होता है जिसे परिभाषित किया जाता है कि कार्य कहां परिभाषित किया गया है, इस मामले में वैश्विक वातावरण (यदि इसे किसी अन्य कार्य के अंदर परिभाषित किया गया था तो माता-पिता पर्यावरण उस के लिए env होगा समारोह)।

जब आप f1 फोन और यह getter तो गेटर चर foo, यह पहली अपने परिवेश से लग रहा है खोजने की कोशिश करता कहता है, वहाँ यह नहीं मिल रहा है, तो अपनी मूल वातावरण जिसमें वैश्विक env है और साथ foo पाता में लग रहा है 1.

का मूल्य आपकी सोच गतिशील स्कॉइंग की रेखाओं के साथ जाती है, जो फ्रेम अनुमानित है। जब f1 कहा जाता है तो इसे अपना पर्यावरण प्राप्त होता है (जिसके भीतर foo को मान 2 असाइन किया जाएगा), तो यह getter फ़ंक्शन को कॉल करता है। foo का वातावरण getter के env (शाब्दिक scoping) की मूल नहीं है, लेकिन f1 का वातावरण getter के बाद से f1 से बुलाया गया था getter की मूल फ्रेम है, इसलिए f1 के वातावरण में देखने के लिए आप get बताने की आवश्यकता पैरेंट वातावरण की बजाय पैरेंट फ्रेम में देखने के लिए कार्य करें।

इसका सारांश यह है कि अभिभावक पर्यावरण वह वातावरण है जहां एक फ़ंक्शन परिभाषित किया गया था (लेक्सिकल स्कॉइंग), पैरेंट फ्रेम वह फ्रेम/वातावरण है जहां से फ़ंक्शन को कॉल किया गया था (नकली गतिशील स्कोपिंग)।

+2

+1 बहुत अच्छा स्पष्टीकरण, धन्यवाद।यह स्वीकार्य उत्तर होने का हकदार है, यदि आप मेरे कोड समाधान को मर्ज करते हैं, तो मैं अपना जवाब हटा दूंगा, इसलिए आपका स्वीकार किया जा सकता है। – Andrie

+0

@Andrie मुझे लगता है कि दोनों उत्तरों अच्छे हैं, आपने तत्काल समस्या हल की है और मैंने पृष्ठभूमि दी है। मुझे शेष दोनों के साथ कोई समस्या नहीं है और जिसे स्वीकार किया जाता है वह मूल पोस्टर का निर्णय होना चाहिए। मैं आपके अपवित्र की सराहना करता हूं। –

+0

दोनों के लिए धन्यवाद, यह बहुत उपयोगी था। – hgcrpd

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