2013-08-20 9 views
6

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

if(load.dat) load("myworkspace.RData") 

जहां load.dat एक तार्किक और डेटा की आवश्यकता myworkspace.RData में संग्रहीत किया जाता है। जब मैं रैपर फ़ंक्शन को कॉल कर रहा हूं जो कई प्लॉट्स के माध्यम से लूप करता है और आउटपुट करता है, तो मैं प्रत्येक कॉल में वर्कस्पेस को आंतरिक फ़ंक्शन पर फिर से लोड नहीं करना चाहता हूं। मैंने सोचा कि मैं रैपर फ़ंक्शन में एक बार वर्कस्पेस लोड कर सकता हूं, फिर आंतरिक फ़ंक्शन उस डेटा तक पहुंच सकता है, लेकिन मुझे अन्यथा बताई गई त्रुटि मिली।

तो मेरी समझ तब थी जब कोई फ़ंक्शन अपने स्थानीय वातावरण में चर नहीं ढूंढ सकता (जब फ़ंक्शन कहलाता है) बनाया जाता है, तो फ़ंक्शन चर के लिए मूल वातावरण को देखेगा।

मुझे लगता है कि आंतरिक फ़ंक्शन कॉल में मूल वातावरण बाहरी फ़ंक्शन कॉल होगा। जाहिर है यह सच नहीं है:

func1 <- function(...){ 
    print(var1) 
} 

func2 <- function(...){ 
    var1 <- "hello" 
    func1(...) 
} 

> func2() 
Error in print(var1) : object 'var1' not found 

कई सवाल, भाषा के मैनुअल, और this वास्तव में उपयोगी ब्लॉग पोस्ट पढ़ने के बाद, मैं के साथ आया था निम्नलिखित:

var1 <- "hello" 
save(list="var1",file="test.RData") 
rm(var1) 

func3 <- function(...){ 
    attach("test.RData") 
    func1(...) 
    detach("file:test.RData") 
} 

> func3() 
[1] "hello" 

वहाँ करने के लिए एक बेहतर तरीका है इस? func1func2 द्वारा बनाए गए स्थानीय वातावरण में अपरिभाषित चर के लिए क्यों नहीं दिखता है, जब यह func2 था जिसे func1 कहा जाता है?

नोट: मुझे नहीं पता था कि इस सवाल को कैसे नामित किया जाए। अगर किसी के पास बेहतर सुझाव हैं तो मैं इसे बदल दूंगा और इस लाइन को संपादित कर दूंगा।

बंद
+2

शाब्दिक scoping का लिंक जोड़ का मतलब समारोह अपनी मूल वातावरण है, जो जरूरी बुला वातावरण नहीं है में अपरिभाषित प्रतीकों के लिए दिखेगा। इसे भी देखें: https://github.com/hadley/devtools/wiki/Environments –

+0

@ Ferdinand.kraft लिंक के लिए धन्यवाद। मैं इस दोपहर के माध्यम से काम करूंगा। – dayne

+0

यदि आपका डेटा डेटाफ्रेम के रूप में है, तो आप पैकेज 'data.table' का उपयोग कर सकते हैं, और' func3' के अंदर 'func1'' के तर्क के रूप में अपनी तालिकाओं को पास कर सकते हैं। यह पैकेज संदर्भ द्वारा काम करता है और आपके डेटा की अवांछित प्रतियां नहीं बनाता है। –

उत्तर

7

शाब्दिक scoping समझाने के लिए, निम्नलिखित पर विचार:

:

पहले के एक सैंडबॉक्स परिवेश ओह-तो-आम R_GlobalEnv बनाने के लिए, केवल से बचने के लिए करते हैं

sandbox <-new.env() 

अब हम इसके अंदर दो कार्य डालते हैं: f, जो x नामक एक चर के लिए दिखता है; और g है, जो एक स्थानीय x परिभाषित करता है और कहता है f:

sandbox$f <- function() 
{ 
    value <- if(exists("x")) x else "not found." 
    cat("This is function f looking for symbol x:", value, "\n") 
} 

sandbox$g <- function() 
{ 
    x <- 123 
    cat("This is function g. ") 
    f() 
} 

तकनीकी: कंसोल में समारोह परिभाषाओं में प्रवेश तो कारण बनता है संलग्न वातावरण R_GlobalEnv के लिए निर्धारित किया है, इसलिए हम स्वयं से मिलान करने के f और g के बाड़ों के लिए मजबूर पर्यावरण जहां वे "संबंधित" हैं:

environment(sandbox$f) <- sandbox 
environment(sandbox$g) <- sandbox 

g पर कॉल करना। स्थानीय चर x=123f से नहीं मिला है:

> sandbox$g() 
This is function g. This is function f looking for symbol x: not found. 

अब हम वैश्विक वातावरण में एक x बना सकते हैं और g कहते हैं।समारोह f सैंडबॉक्स के माता पिता, जो R_GlobalEnv होने में खिलौने के डिब्बे में पहले x के लिए दिखाई देगा, और उसके बाद:

> x <- 456 
> sandbox$g() 
This is function g. This is function f looking for symbol x: 456 

बस ऐसे ही f लग रहा है अपने बाड़े में के लिए x पहले जाँच करने के लिए, हम एक x डाल सकते हैं वहाँ और g फोन:

> sandbox$x <- 789 
> sandbox$g() 
This is function g. This is function f looking for symbol x: 789 

निष्कर्ष: आर में प्रतीक देखने नेस्टेड समारोह के निष्पादन के दौरान बनाए गए संलग्न वातावरण की श्रृंखला, नहीं मूल्यांकन फ्रेम इस प्रकार है कहता है।

संपादित करें: बस this very interesting answer from Martin Morgan on the related subject of parent.frame() vs parent.env()

+0

यह मैंने देखा है सबसे अच्छा उदाहरण है। आपको बहुत - बहुत धन्यवाद! मैं वास्तव में वातावरण और फ्रेम में अंतर को समझ नहीं रहा था। – dayne

2

आप इस्तेमाल कर सकते हैं:

f2 <- function(...){ 
    f1 <- function(...){ 
    print(var1) 
    } 
    var1 <- "hello" 
    f1(...) 
} 
f2() 
+0

ठीक है, लेकिन मुझे आंतरिक कार्य को स्टैंड-अलोन फ़ंक्शन के रूप में उपयोग करने में सक्षम होना चाहिए। जब भी मैं बाहरी फ़ंक्शन को कॉल करता हूं (कोड का एक समूह डुप्लिकेट का उल्लेख नहीं करता) मैं आंतरिक फ़ंक्शन को फिर से परिभाषित नहीं करना चाहता था। – dayne

+0

फिर मेरी राय में सबसे साफ सेटिंग: अपने सभी डेटा को एक सूची (my_data) में रखें, फिर इसे अपने फ़ंक्शन के लिए तर्क दें। अतिरिक्त टाइपिंग से बचने के लिए आप (my_data, {}) के साथ फ़ंक्शन के अंदर उपयोग कर सकते हैं। –

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