मूल्यांकन के तहत पहले से ही वादा: पुनरावर्ती डिफ़ॉल्ट तर्क संदर्भ या पहले की समस्याएं?


143

यहाँ मेरा R कोड है। कार्यों को इस प्रकार परिभाषित किया गया है:

f <- function(x, T) {
  10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80
}

g <- function(x, T, f=f) {
  exp(-f(x) / T)
}

test <- function(g=g, T=1) { 
  g(1, T)
}

रनिंग त्रुटि है:

> परीक्षण ()
परीक्षण में त्रुटि ():
मूल्यांकन के तहत पहले से ही वादा: पुनरावर्ती डिफ़ॉल्ट तर्क संदर्भ या पहले की समस्याएं?

अगर मैं की परिभाषा स्थानापन्न fके उस में gहै, तो त्रुटि दूर चला जाता है।

मैं सोच रहा था कि क्या त्रुटि थी? यह कैसे सही करने के लिए करता है, तो की परिभाषा स्थानापन्न नहीं है fकी है कि में g? धन्यवाद!


अपडेट करें:

धन्यवाद! दो सवाल:

(1) यदि फ़ंक्शन testआगे के लिए तर्क लेता है f, तो क्या आप कुछ ऐसा जोड़ेंगे test <- function(g.=g, T=1, f..=f){ g.(1,T, f.=f..) }? अधिक पुनरावृत्ति वाले मामलों में, क्या यह अधिक जोड़ने के लिए एक अच्छा और सुरक्षित अभ्यास है ?

(2) यदि fएक गैर-फ़ंक्शन तर्क है, उदाहरण के लिए g <- function(x, T, f=f){ exp(-f*x/T) }और test <- function(g.=g, T=1, f=f){ g.(1,T, f=f.) }, औपचारिक और वास्तविक गैर-कार्यात्मक तर्क दोनों के लिए एक ही नाम का उपयोग करना एक अच्छा और सुरक्षित अभ्यास होगा या इससे कुछ संभावित परेशानी हो सकती है?

जवाबों:


159

फॉर्म के औपचारिक तर्क इसका x=xकारण बनते हैं। दो उदाहरणों को हटाते हुए, जहां वे होते हैं:

f <- function(x, T) {
   10 * sin(0.3 * x) * sin(1.3 * x^2) + 0.001 * x^3 + 0.2 * x + 80 
}

g <- function(x, T, f. = f) {  ## 1. note f.
   exp(-f.(x)/T) 
}

test<- function(g. = g, T = 1) {  ## 2. note g.
   g.(1,T) 
}

test()
## [1] 8.560335e-37

2
धन्यवाद! दो प्रश्न (1) यदि फ़ंक्शन टेस्ट आगे f के लिए एक तर्क लेता है , तो क्या आप परीक्षण जैसा कुछ जोड़ेंगे <- function (g = = g, T = 1, f .. = f) {g। (1, T, f। = च ..)} ? अधिक पुनरावृत्ति वाले मामलों में, क्या यह अधिक जोड़ने के लिए एक अच्छा और सुरक्षित अभ्यास है ? (2) यदि f एक गैर-फ़ंक्शन तर्क है, उदाहरण के लिए g <- function (x, T, f = f) {exp (-f x / T)} * और परीक्षण <- function (g। = G, T)। = 1, f = f) {g। (1, T, f = f।)} , औपचारिक और वास्तविक दोनों गैर-कार्यात्मक तर्कों के लिए एक ही नाम का उपयोग करना एक अच्छा और सुरक्षित अभ्यास होगा या इससे कुछ संभावित परेशानी हो सकती है?
टिम

16
कोई और उपाय? मैं कुछ तर्कों को कार्यों की श्रृंखला (लगभग 5 स्तरों) से नीचे पारित कर रहा हूं, और यह समाधान बन सकता है .....cumbersome। :)
रोमन लुसट्रिक

2
@ RomanLuštrik यदि आप तर्कों को पारित कर रहे हैं और आप उनमें से कुछ को सुरक्षित रूप से अनदेखा कर सकते हैं, तो ...फ़ंक्शन श्रृंखला के नीचे तर्कों को पारित करने के लिए दीर्घवृत्त या एक सूची का उपयोग करें । यह सब कुछ पूर्व-परिभाषित करने की तुलना में बहुत अधिक लचीला (अच्छे और बीमार के लिए) है। आप केवल यह सुनिश्चित कर सकते हैं कि दीर्घवृत्त (या सूची) में आपके मूल तर्क को सुनिश्चित करने के लिए कुछ जाँचों को जोड़ने की आवश्यकता है।
रुसेलपिएरेस

2
यहां एक और विकल्प स्पष्ट रूप से सक्रिय वादे के आकस्मिक बल को दरकिनार करते हुए, एक मूल फ्रेम में तर्कों को खोजने का प्रयास है, जैसे get("f", envir = parent.frame())
केविन उशे

1
केवल आवश्यकता यह है कि आप बाएँ और दाएँ हाथ की तरफ एक ही नाम का उपयोग न करें। इसके अलावा यह सिर्फ स्टाइल है।
जी। ग्रेंथिएक

13

यदि आप तर्क मूल्यांकन संदर्भ को स्पष्ट करते हैं, तो आप एक ही नाम की समस्या से बचते हैं:

f <- function(x) {
  10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80
}
g <- function(x, t=1, f=parent.frame()$f) {
  exp(-f(x) / t)
}
test <- function(g=parent.frame()$g, t=1) { 
  g(1,t)
}
test()
[1] 8.560335e-37

2
यह एक बेहतर तरीका है, मुझे लगता है कि निर्दिष्ट पर्यावरण अधिक स्पष्ट है
बादलों की छंटनी

1

मुझे जी। ग्रोथेंडिक उत्तर पसंद है, लेकिन मैं सोच रहा था कि आपके मामले में फ़ंक्शन के मापदंडों में फ़ंक्शन नाम शामिल नहीं करना इस तरह से अधिक सरल है:

f <- function(x, T) {
  10 * sin(0.3 * x) * sin(1.3 * x^2) + 0.001 * x^3 + 0.2 * x + 80 
}
g <- function(x, T) {
  exp(-f(x)/T) 
}
test<- function(T = 1) {
  g(1,T)
}
test()
## [1] 8.560335e-37

1

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

यह काम नहीं करता:

x = 4
my.function <- function(x = x){} 
my.function() # recursive error!

लेकिन यह काम करता है:

x = 4
my.function <- function(x){} 
my.function(x = x) # works fine!

फ़ंक्शन तर्क अपने स्थानीय वातावरण में मौजूद हैं।

आर पहले स्थानीय वातावरण में, फिर वैश्विक वातावरण में चर की तलाश करता है। यह वैसा ही है जैसे किसी फ़ंक्शन के अंदर एक वैरिएबल का वैसा ही नाम हो सकता है जैसा कि वैश्विक परिवेश में एक वैरिएबल का होता है, और R स्थानीय परिभाषा का उपयोग करेगा।

फ़ंक्शन तर्क परिभाषाएँ होने के कारण उनका अपना स्थानीय वातावरण होता है, इसीलिए आपके पास अन्य तर्क मूल्यों के आधार पर डिफ़ॉल्ट तर्क मान हो सकते हैं, जैसे

my.function <- function(x, two.x = 2 * x){}

तो यही कारण है कि आप किसी फ़ंक्शन को DEFINE नहीं my.function <- function(x = x){}कर सकते, लेकिन आप फ़ंक्शन का उपयोग करके कॉल कर सकते हैं my.function(x = x)। जब आप फ़ंक्शन को परिभाषित करते हैं, तो आर भ्रमित हो जाता है क्योंकि यह तर्क x =को स्थानीय मान के रूप में पाता है x, लेकिन जब आप फ़ंक्शन x = 4को उस स्थानीय वातावरण में कॉल करते हैं जिसे आप कॉल कर रहे हैं।

इसलिए तर्क का नाम बदलकर या अन्य उत्तरों में वर्णित पर्यावरण को स्पष्ट रूप से निर्दिष्ट करके त्रुटि को ठीक करने के अलावा, आप यह भी निर्दिष्ट कर सकते हैं कि x=xजब आप इसे परिभाषित करने के बजाय फ़ंक्शन को कॉल करते हैं। मेरे लिए, यह निर्दिष्ट करना कि x=xकॉल में सबसे अच्छा समाधान था, क्योंकि इसमें अतिरिक्त वाक्यविन्यास शामिल नहीं है और अधिक से अधिक चर नाम संचय करना है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.