16

"आर promises पास नहीं करता है, मान नहीं है। वादा तब किया जाता है जब इसे पहले मूल्यांकन किया जाता है, जब यह पारित नहीं होता है।", 0 ग्रोथेंडिक द्वारा this answer देखें। हैडली की पुस्तक का जिक्र करते हुए this question भी देखें।आर के 'आलसी मूल्यांकन जाल' में कैसे नहीं आते

सरल उदाहरणों में इस तरह के रूप में

> funs <- lapply(1:10, function(i) function() print(i)) 
> funs[[1]]() 
[1] 10 
> funs[[2]]() 
[1] 10 

यह खाते में इस तरह के unintuitive व्यवहार लेने के लिए संभव है।

हालांकि, मैं खुद को दैनिक विकास के दौरान अक्सर इस जाल में पड़ता हूं। मैं एक कार्यात्मक प्रोग्रामिंग शैली का पालन करता हूं, जिसका अर्थ है कि मेरे पास अक्सर एक फ़ंक्शन ए होता है जो एक फ़ंक्शन बी लौटाता है, जहां बी कुछ मायनों के आधार पर होता है जिसके साथ ए को बुलाया जाता है। निर्भरता उपर्युक्त उदाहरण के रूप में देखने के लिए आसान नहीं है, क्योंकि गणना जटिल हैं और कई पैरामीटर हैं।

ऐसी समस्या को देखते हुए समस्याएं डीबग करना मुश्किल हो जाता है, क्योंकि सभी गणना सुचारू रूप से चलती है - सिवाय इसके कि परिणाम गलत है। परिणामों के केवल एक स्पष्ट सत्यापन समस्या को प्रकट करता है।

शीर्ष पर क्या आता है यह है कि अगर मैंने ऐसी समस्या देखी है, तो भी मुझे सच में यकीन नहीं है कि मुझे कौन से चर force और जो मैं नहीं करता हूं।

मैं कैसे सुनिश्चित कर सकता हूं कि इस जाल में न पड़ें? क्या कोई प्रोग्रामिंग पैटर्न है जो इसे रोकता है या कम से कम यह सुनिश्चित करता है कि मुझे पता है कि कोई समस्या है?

+1

ऐसा लगता है कि यह आपकी प्रोग्रामिंग शैली का फिर से मूल्यांकन करने का एक अच्छा अवसर हो सकता है यदि आप ऐसी भाषा को मजबूर कर रहे हैं जो आप ऐसा करने के लिए कर रहे हैं जो इसे स्वाभाविक रूप से करने के लिए सेट नहीं है ... – Chase

+6

... यही कारण है कि मैं उन समस्याओं के लिए पूछ रहा था जो इस समस्या को बाधित करते हैं। ;-) – jhin

+0

यह सवाल ऐतिहासिक ब्याज की अब भी है, लेकिन आज के पाठकों को पता है कि आर 3.4.1 (शायद के रूप में जल्दी 3.2.0 के रूप में) ऑप्स में उदाहरण के रूप में कारणों funs पोस्ट दिलचस्पी हो सकती है [[5]]() परिणामस्वरूप '5'। – russellpierce

उत्तर

11

आप अंतर्निहित पैरामीटर के साथ काम कर रहे हैं, जो कि सबसे अच्छा अभ्यास नहीं है। आपके उदाहरण में, निहित पैरामीटर i है। एक और तरीका है rework करने के लिए यह होगा:

library(functional) 
myprint <- function(x) print(x) 
funs <- lapply(1:10, function(i) Curry(myprint, i)) 
funs[[1]]() 
# [1] 1 
funs[[2]]() 
# [1] 2 

यहाँ, हम स्पष्ट रूप से Curry का उपयोग करके कार्य करने के लिए पैरामीटर निर्दिष्ट। ध्यान दें कि हम print सीधे घुमा सकते थे लेकिन चित्रकारी उद्देश्यों के लिए यहां नहीं थे।

Curry पूर्व-निर्दिष्ट पैरामीटर के साथ फ़ंक्शन का एक नया संस्करण बनाता है। यह पैरामीटर विनिर्देश को स्पष्ट करता है और आपके द्वारा चलाए जा रहे संभावित मुद्दों से बचाता है क्योंकि Curry बल मूल्यांकन (कोई ऐसा संस्करण है जो नहीं करता है, लेकिन यह यहां सहायता नहीं करेगा)।

एक अन्य विकल्प माता पिता समारोह के पूरे माहौल पर कब्जा, इसे कॉपी, और यह आपके नए कार्य की मूल env बनाना है:

funs2 <- lapply(
    1:10, function(i) { 
    fun.res <- function() print(i) 
    environment(fun.res) <- list2env(as.list(environment())) # force parent env copy 
    fun.res 
    } 
) 
funs2[[1]]() 
# [1] 1 
funs2[[2]]() 
# [1] 2 

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

+0

धन्यवाद, मुझे लगता है कि यह केवल संकेत था कि मुझे चाहिए (अंतर्निहित पैरामीटर निर्भरताओं के संबंध में)! क्या यह अनिवार्य रूप से अन्य कार्यों में सब कुछ निकालने के लिए बंद बनाम उपयोग करने के लिए उबाल नहीं है? मुझे लगता है, मैं शुरुआत में हैडली के बंद होने के प्रचार के कारण इस शैली को शुरू कर रहा था (http://adv-r.had.co.nz/Functional-programming.html)। – jhin

+0

विशिष्ट कार्यान्वयन के संबंध में, 'बल (i) के समतुल्य 'करी (myprint, i)' लौटा रहा है; फ़ंक्शन() myprint (i) '? मैं एक गैर-मानक पैकेज पर निर्भर प्रोग्रामिंग शैली का ऐसा अभिन्न हिस्सा बनाने में थोड़ा संकोच करता हूं। उदाहरण पर विचार करें सहकर्मियों के लिए पठनीयता, कार्यात्मक प्रोग्रामिंग के बारे में जानकार नहीं है। – jhin

+1

बंद करने का सबसे आम उपयोग एक सतत लेकिन संशोधित स्थिति के साथ कार्यों को बनाना है। आप कार्यों के लिए निहित पैरामीटर निर्दिष्ट करने के लिए उनका उपयोग कर सकते हैं, लेकिन फिर, यह अच्छी प्रैक्टिस की तरह प्रतीत नहीं होता है। – BrodieG

6

जैसा कि अन्य ने बताया, यह आर में प्रोग्रामिंग की सबसे अच्छी शैली नहीं हो सकती है, लेकिन, एक आसान विकल्प सिर्फ सब कुछ मजबूर करने की आदत में होना है। यदि आप ऐसा करते हैं, तो आपको एहसास है कि आपको वास्तव में force पर कॉल करने की आवश्यकता नहीं है, केवल प्रतीक का मूल्यांकन करना होगा।

myfun<-function(x,y,z){ 
    x;y;z; 
    ## code 
} 
+1

'बल' का शब्दशः, या "कुरूपता" इसका बहुत ही उद्देश्य है: यह _intent_ स्पष्ट-सख्त मूल्यांकन लगाया जा रहा है। – egnha

5

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

+0

अब यह कुछ अच्छी खबर है! :) – jhin

+0

एक बार अधिक जानकारी उपलब्ध होने पर संशोधन को प्रोत्साहित करने के लिए +1 किया गया था। ;) – jhin

+0

कुछ प्रासंगिक परिवर्तन वास्तव में आर 3.2.0 में शामिल किए गए हैं। मुझे लगता है कि यह सब कुछ आप जिक्र कर रहे थे? या अधिक परिवर्तन योजनाबद्ध हैं? – jhin

0

आर एक समारोह है कि आलसी मूल्यांकन के खिलाफ की रक्षा में मदद करता है, बंद निर्माण इस तरह की स्थितियों में है: forceAndCall()

ऑनलाइन आर सहायता दस्तावेज़ से:

forceAndCall अधिक यथोचित व्यवहार करने के लिए जब परिणाम समारोह लागू किया द्वारा लौटाए गए एक बंद है कि अपने तर्कों पर कब्जा कर लिया है लागू की तरह उच्च आदेश कार्यों को परिभाषित करने में मदद करने के लिए है।

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