2012-06-05 12 views
6

इस समारोह a(), जो तर्क है कि में पारित किया गया था बाहर प्रिंट पर विचार करें:विकल्प() का उपयोग तर्क के नाम, कई स्तरों प्राप्त करने के लिए

a <- function(x) { 
    message("The input is ", deparse(substitute(x))) 
} 

a("foo") 
# The input is "foo" 

tmplist <- list(x1 = 1, x2=2) 
a(tmplist) 
# The input is tmplist 

काम करता है।

b <- function(y) { 
    a(y) 
} 

b("foo") 
# The input is y 

b(tmplist) 
# The input is y 

एक समाधान काम करने के लिए एक और substitute में रैप करने के लिए है लगता है कि और एक eval: लेकिन जब a() एक और समारोह से कहा जाता है, यह अब बाहर मूल तर्क नाम प्रिंट

a1 <- function(x) { 
    message("The input is ", deparse(eval(substitute(substitute(x)), parent.frame()))) 
} 

a1("foo") 
# The input is "foo" 

tmplist <- list(x1 = 1, x2=2) 
a1(tmplist) 
# The input is tmplist 

b1 <- function(y) { 
    a1(y) 
} 

b1("foo") 
# The input is "foo" 

b1(tmplist) 
# The input is tmplist 

लेकिन यह सुरुचिपूर्ण लगता है। और अगर मैं एक और परत जोड़ता हूं तो यह विफल हो जाता है:

c1 <- function(z) { 
    b1(z) 
} 
c1("foo") 
# The input is z 

क्या मूल तर्क प्राप्त करने का एक अच्छा, सामान्य तरीका है?

+0

मैं वातावरण से निपटने पर कोई विशेषज्ञ हूँ, लेकिन मुझे लगता है कि या तो के रूप में kohske किया 'parent.frame' के साथ खेल, या एक वैश्विक चर निर्दिष्ट करने के लिए अपने ही विकल्प हैं। आर सी के तरीके के संदर्भ में पास नहीं करता है। –

उत्तर

3

मुझे यकीन है कि यह अच्छी तरह से इस सभी स्थितियों में काम करेंगे, लेकिन कोशिश नहीं कर रहा हूँ इस:

f0 <- function(x) { 
    nn <- substitute(x) 
    i <- 1 
    while(TRUE) { 
    on <- do.call("substitute", list(as.name(nn), parent.frame(i))) 
    if (on == nn) break; 
    nn <- on 
    i <- i + 1 
    } 
    message("The input is ", nn) 
} 

f1 <-function(.f1) f0(.f1) 
f2 <- function(.f2) f1(.f2) 

और फिर,

> f2(foo) 
The input is foo 
> f1(poo) 
The input is poo 
> f0(moo) 
The input is moo 
> f2(";(") 
The input is ;(
> f1(":)") 
The input is :) 
> f0(":p") 
The input is :p 
+0

यह बहुत अच्छा है। लेकिन यदि चर के नाम दो लगातार चरणों में समान हैं, तो मुझे लगता है कि यह वास्तव में समाप्त होने से पहले इसे रोकने में मूर्खतापूर्ण है। मान लीजिए कि आप f1 और f2 को परिभाषित करते हैं, इसलिए वे तर्क के रूप में 'xx' लेते हैं - फिर यह वहां रुक जाता है। हो सकता है कि समाधान 'i == sys.nframe() 'तक लूपिंग रखना है। – wch

+0

हम्म, हाँ ... कैसे हल करें ...? – kohske

0

कैसे रिकर्सिवली अपने फ़ंक्शन को कॉल के बारे में जब

deparse(substitute(x))!=deparse(eval(substitute(substitute(x)), parent.frame()) 
1

हालांकि यह अपने अधिकार में एक दिलचस्प सवाल है, मुझे आश्चर्य है कि सबसे अच्छा समाधान बस पास करना है या नहीं परिवर्तनीय नाम एक चरित्र के रूप में, यानी उद्धरण में। तब इनमें से कोई भी जरूरी नहीं है। यदि नाम से संबंधित ऑब्जेक्ट की आवश्यकता है, तो इसे फ़ंक्शन के भीतर उपयोग करने के तरीके के आधार पर get या as.name और do.call के साथ प्राप्त किया जा सकता है।

> f0 <- function(x) {message("The input is ", x)} 
> f1 <- function(.f1) f0(.f1) 
> f2 <- function(.f2) f1(.f2) 
> f2("aa") 
The input is aa 
> f1("bb") 
The input is bb 
> f0("cc") 
The input is cc 
+0

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

+0

हम्मम्म .... मेरा मानना ​​है कि चेन की त्रुटि को "प्रचारित करने" का एक तरीका है, ताकि एक बुलाए गए फ़ंक्शन में एक त्रुटि शीर्ष फ़ंक्शन में एक संदेश ट्रिगर करेगी, जहां आप चर के "सही नाम" को जानते हैं। कोई भी जो 'त्रुटि' और 'trycatch' के उपयोग में मुझसे बेहतर शिक्षित है, यहां कूदने में सक्षम हो सकता है। एक बार फिर, हम सही सवाल पूछने के महत्व को देखते हैं! –

+1

@wch: कार्ल की आखिरी टिप्पणी पर विस्तार करने के लिए, सही सवाल यह है कि आप वास्तव में क्या करने की कोशिश कर रहे हैं, इस बारे में नहीं कि आप इसे कैसे करने की कोशिश कर रहे हैं। यही नहीं है, "मैं वाई करने के लिए एक्स का उपयोग कैसे करूं?"या बदतर," मैं एक्स कैसे करूं? "इसके बजाय पूछें" मैं वाई कैसे करूँ? मैंने एक्स की कोशिश की है, लेकिन यह काम नहीं कर रहा है। " – Aaron

1

kohske के जवाब अनुकूल है, यहाँ कुछ है कि काम करता है, लेकिन अगर चर लगातार दो फ्रेम में एक ही नाम है समय से पहले ही फ्रेम ढेर ऊपर जाना बंद नहीं करता है, है। मुझे नहीं पता कि यह सभी परिस्थितियों में सही तरीके से काम करता है, लेकिन ऐसा लगता है कि मेरी ज़रूरतें पूरी होती हैं। तार बनाम चर के उद्धरण पहले से थोड़ा अलग है, लेकिन यह मेरे मामले के लिए ठीक है।

a <- function(x) { 
    newname <- substitute(x) 

    # Travel up the frame stack until we hit the top. 
    for(i in seq_len(sys.nframe())) { 
    oldname <- do.call("substitute", list(as.name(newname), parent.frame(i))) 
    newname <- oldname 
    } 
    message("The input is ", deparse(newname)) 
} 

b <- function(y) a(y) 

c <- function(z) b(z) 

a("adsf") 
# The input is adsf 
a(foo) 
# The input is foo 

b("adsf") 
# The input is adsf 
b(foo) 
# The input is foo 

c("adsf") 
# The input is adsf 
c(foo) 
# The input is foo 
संबंधित मुद्दे