2014-10-30 7 views
9

मैं एक आर पैकेज का उपयोग कर रहा हूं, जिसमें 2 फ़ंक्शंस एफ 1 और एफ 2 (एफ 2 कॉलिंग एफ 1 के साथ)
मैं फ़ंक्शन f1 को ओवरराइट करना चाहता हूं।आर: पैकेज से किसी फ़ंक्शन को ओवरराइट करने का सही तरीका क्या है?

चूंकि 2.15 और पैकेज में नेमस्पेस का अनिवार्य उपयोग, यदि मैं केवल नए फ़ंक्शन को स्रोत करता हूं, तो यह वास्तव में वैश्विक वातावरण में उपलब्ध है (यानी कंसोल में केवल f1 (x) को कॉल करना नया परिणाम देता है)। हालांकि, कॉलिंग f2 अभी भी पैक किए गए फ़ंक्शन f1 का उपयोग करेगा। (क्योंकि नेमस्पेस खोज पथ को संशोधित करता है, और इसे here in the Writing R Extensions ट्यूटोरियल समझाया गया है)
नए के साथ f1 को पूरी तरह से बदलने का उचित तरीका क्या है? (पैकेज को फिर से बनाने के अलावा!) यह कई स्थितियों में उपयोगी हो सकता है। उदाहरण के लिए यदि पैकेज में कोई बग है जिसे आपने विकसित नहीं किया है। या यदि आप अभी भी विकास के दौरान अपने पैकेजों को फिर से बनाना नहीं चाहते हैं।

मैं समारोह के बारे में पता

assignInNamespace("f1",f1,ns="mypackage") 

हालांकि, मदद पृष्ठ ?assignInNamespace थोड़ा enignmatic है और अधिक जानकारी दिए बिना इसका उपयोग करने से लोगों को हतोत्साहित करने के लिए लगता है, और मैं इस पर कोई सर्वश्रेष्ठ व्यवहार सुझाव नहीं पा सके आधिकारिक सीआरएएन ट्यूटोरियल। और इस फ़ंक्शन को कॉल करने के बाद:

# Any of these 2 calls return the new function 
mypackage::f1 
getFromNamespace(x = "f1", envir = as.environment("package:mypackage")) 

# while this one still returns the old packaged version 
getFunction(name = "f1", where = as.environment("package:mypackage")) 

यह बहुत परेशान है। खोज पथ कैसे प्रभावित होता है?

अब मैं ऐसे lockEnvironment समारोह को संशोधित करने के लिए इतना है कि library पैकेज नाम स्थान को लॉक नहीं करता, और मैं इसे बाद के चरण एक बार मैं F1 जगह ले ली है पर लॉक कर सकते हैं (जो वास्तव में एक अच्छा नहीं लगता है के रूप में कुछ बदसूरत बातें कर रहा हूँ के लिए

  1. वास्तव में क्या एक पैकेज नाम स्थान (जो माना जाता है के मामले में assignInNamespace क्या करता है बंद किया जा करने के लिए)
  2. अच्छा अभ्यास क्या हैं: अभ्यास)

    तो मूल रूप से मैं 2 प्रश्न हैं?

आपके अनुभव को साझा करने के लिए बहुत धन्यवाद।

संपादित करें: इस प्रश्न में रुचि रखने वाले लोगों को this blog post बहुत दिलचस्प लगता है।

+1

महान प्रश्न। मैं हाल ही में स्पष्टीकरण की खोज कर रहा हूं, इस विषय पर एक [पुराना धागा] (https://stat.ethz.ch/pipermail/r-help/2008-August/171217.html) पाया गया है, जो प्रासंगिक प्रतीत होता है । – tonytonov

+0

@tonytonov आप के लिए धन्यवाद लिंक। मुझे यह समझने में कामयाब नहीं रहा कि पैकेज के मामले में 'अनलॉक बाइंडिंग' क्या कर रहा था। ऐसा लगता है कि केवल 'असाइनइन नेमस्पेस' करने से बिल्कुल वही परिणाम हो रहा है। कोई सुराग? – RockScience

+0

वास्तव में नहीं। मेरे अनुभव के अनुसार, 'असाइनइन नामस्थान' काम करता है या पैकेज के आधार पर काम नहीं करता है, और मुझे नहीं पता कि ऐसा क्यों होता है। यदि यह विफल रहता है, तो 'अनलॉक बाइंडिंग' से युक्त समाधान या तो काम नहीं करता है। – tonytonov

उत्तर

3

यहां कई सारे मामले हैं।

यदि यह किसी और का पैकेज
में एक बग है तो सबसे अच्छा अभ्यास पैकेज मेंटेनर संपर्क करें और उन्हें मनाने इसे ठीक करने के लिए है। इस तरह हर कोई ठीक हो जाता है, सिर्फ आप ही नहीं।

यदि यह एक बग, जबकि अपने खुद के पैकेज के विकास
तो फिर तुम एक कार्यप्रवाह खोजने के लिए जहां पुनर्निर्माण पैकेज के लिए आसान है की जरूरत है। devtools पैकेज का उपयोग करने और build(mypackage) टाइप करने या RStudio में "बटन & रीलोड" बनाएं; आर्किटेक्ट में "आर सीएमडी बिल्ड" का उपयोग करना)।

तुम सिर्फ एक मौजूदा पैकेज
को अलग व्यवहार चाहते हैं, तो यह इस तरह के रूप में एक बग नहीं है, या पैकेज मेंटेनर ठीक है कि आप चाहते हैं नहीं होगा, तो आप आप को बनाए रखने करना होगा f1 की अपनी प्रति। मौजूदा पैकेज में इसे ओवरराइड करने के लिए assignInNamespace का उपयोग करना एक्सप्लोर करने के लिए ठीक है, लेकिन यह थोड़ा हैकी है इसलिए यह स्थायी समाधान के लिए वास्तव में उपयुक्त नहीं है।

आपकी सबसे अच्छी शर्त f1 और f2 की प्रतियां युक्त अपना पैकेज बनाना है। यह लगता है कि यह कम प्रयास है, क्योंकि आप केवल f2 <- existingpackage::f2 परिभाषित कर सकते हैं।


टिप्पणी के जवाब में:

दूसरे तथा तीसरे मामलों समझ में आता है, तो आप अकेले हैं लेकिन वे संकुल जो संकुल के रूप में मेरे संगठन के मामले में मुश्किल है का निर्माण और स्थापित करने के लिए आवश्यकता होती है दर्जनों कंप्यूटर पर तैनात हैं और मुझे पैकेज अपडेट करने के लिए रूट पहुंच की आवश्यकता है।

तो मौजूदा पैकेज स्रोत की प्रतिलिपि लें, अपने पैच को लागू करें, और इसे अपने कंपनी नेटवर्क या गिथब या बिटबकेट पर होस्ट करें। तब अद्यतन पैकेज के माध्यम से

install.packages("//some/network/path/mypackage_0.0-1.tar.gz", repos = NULL) 

या

library(devtools) 
install_github("mypackage", "mygithubusername") 

प्रोग्राम के रूप में स्थापित किया जा सकता चूंकि स्थापना सिर्फ कोड की एक पंक्ति है, आप आसानी से के रूप में कई मशीनों को धक्का के रूप में आप की तरह कर सकते हैं। आपको रूट पहुंच की आवश्यकता नहीं है - बस उस लाइब्रेरी फ़ोल्डर में पैकेज स्थापित करें जिसे लिखने के लिए रूट पहुंच की आवश्यकता नहीं है। (Startup और .libPaths नई लाइब्रेरी को परिभाषित करने के लिए सहायता पृष्ठ पढ़ें।) आपको उन मशीनों तक नेटवर्क पहुंच की आवश्यकता होगी, लेकिन मैं आपकी सहायता नहीं कर सकता। अपने नेटवर्क व्यवस्थापक या अपने मालिक से बात करें या जो भी आपको अनुमति दे सकता है।

+1

इन सभी बिंदुओं के लिए सहमत हैं, लेकिन यदि आपके पास समय है तो यह सब काम करता है। ** पहला मामला ** वास्तव में सबसे अच्छा अभ्यास है, लेकिन मुझे इसे मेरे लिए पहले ठीक करने की आवश्यकता है क्योंकि इसे पैकेज मालिक द्वारा सीआरएएन में तय करने में सप्ताह लग सकते हैं। ** द्वितीय और तीसरे मामले ** यदि आप अकेले हैं तो उन्हें समझ में आता है लेकिन उन्हें अपने संगठन के मामले में मुश्किल पैकेजों को बनाने और स्थापित करने की आवश्यकता होती है क्योंकि पैकेजों को दर्जनों कंप्यूटर पर तैनात किया जाता है और मुझे पैकेज अपडेट करने के लिए रूट पहुंच की आवश्यकता होती है । दुर्भाग्य से मुझे लगता है कि आर उन लोगों के लिए डिज़ाइन नहीं किया गया था जो जल्दी में हैं। – RockScience

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

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