डब्ल्यूबी को छोड़कर (जो वास्तव में आपके प्रश्न का उत्तर देने के लिए जरूरी नहीं है) - समस्या का सीधा जवाब लगता है कि असाइनमेंट के दौरान अभिव्यक्तियों का मूल्यांकन कैसे किया जाता है। यहां एक उदाहरण दिया गया है:
In[1505]:=
notGoodQ[x_]:=True;
Clear[g];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
In[1509]:= g/:cccQ[g[x0_]]:=True
During evaluation of In[1509]:= g::nogood: -- Message text not found -- (x0_)
Out[1509]= $Aborted
इसे काम करने के लिए, मैंने जानबूझकर notGoodQ
. की परिभाषा बनाई है हमेशा True
लौटाने के लिए . अब, क्यों था g[x0_]
असाइनमेंट के दौरान TagSetDelayed
. के माध्यम से मूल्यांकन किया गया ? इसका उत्तर यह है कि, जबकि TagSetDelayed
(साथ ही SetDelayed
) एक असाइनमेंट में h/:f[h[elem1,...,elemn]]:=...
कोई भी नियम लागू नहीं करता है जो f
हो सकता है, यह मूल्यांकन करेगा h[elem1,...,elem2]
, साथ ही f
. यहां एक उदाहरण दिया गया है:
In[1513]:=
ClearAll[h,f];
h[___]:=Print["Evaluated"];
In[1515]:= h/:f[h[1,2]]:=3
During evaluation of In[1515]:= Evaluated
During evaluation of In[1515]:= TagSetDelayed::tagnf: Tag h not found in f[Null]. >>
Out[1515]= $Failed
तथ्य यह है कि TagSetDelayed
HoldAll
. है इसका मतलब यह नहीं है कि यह अपने तर्कों का मूल्यांकन नहीं करता है - इसका मतलब केवल यह है कि तर्क बिना मूल्यांकन के आते हैं, और उनका मूल्यांकन किया जाएगा या नहीं, यह TagSetDelayed
के शब्दार्थ पर निर्भर करता है। (जिसे मैंने ऊपर संक्षेप में वर्णित किया है)। SetDelayed
. के लिए भी यही स्थिति है , इसलिए आमतौर पर इस्तेमाल किया जाने वाला कथन कि यह "अपने तर्कों का मूल्यांकन नहीं करता" शाब्दिक रूप से सही नहीं है। एक अधिक सही कथन यह है कि यह तर्कों को बिना मूल्यांकन के प्राप्त करता है और उनका मूल्यांकन एक विशेष तरीके से करता है - r.h.s का मूल्यांकन नहीं करता है, जबकि l.h.s. के लिए, सिर और तत्वों का मूल्यांकन करता है लेकिन सिर के लिए नियम लागू नहीं करता है। इससे बचने के लिए, आप चीजों को HoldPattern
. में लपेट सकते हैं , इस तरह:
Clear[g,notGoodQ];
notGoodQ[x_]:=EvenQ[x];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
g/:cccQ[HoldPattern[g[x0_]]]:=True;
यह गुजरता है। यहाँ कुछ उपयोग है:
In[1527]:= cccQ[g[1]]
Out[1527]= True
In[1528]:= cccQ[g[2]]
During evaluation of In[1528]:= g::nogood: -- Message text not found -- (2)
Out[1528]= $Aborted
हालांकि ध्यान दें कि HoldPattern
. की आवश्यकता है परिभाषा बनाते समय आपके बाएं हाथ के अंदर अक्सर एक संकेत होता है कि फ़ंक्शन कॉल के दौरान आपके सिर के अंदर की अभिव्यक्ति का मूल्यांकन भी हो सकता है, जो आपके कोड को तोड़ सकता है। मेरे कहने का एक उदाहरण यहां दिया गया है:
In[1532]:=
ClearAll[f,h];
f[x_]:=x^2;
f/:h[HoldPattern[f[y_]]]:=y^4;
यह कोड h[f[something]]
. जैसे मामलों को पकड़ने का प्रयास करता है , लेकिन यह स्पष्ट रूप से विफल हो जाएगा क्योंकि f[something]
मूल्यांकन h
पर आने से पहले मूल्यांकन करेगा :
In[1535]:= h[f[5]]
Out[1535]= h[25]
मेरे लिए, HoldPattern
. की आवश्यकता है एल.एच.एस. पर यह एक संकेत है कि मुझे अपने डिज़ाइन पर पुनर्विचार करने की आवश्यकता है।
संपादित करें
डब्ल्यूबी में लोडिंग के दौरान डिबगिंग के संबंध में, एक चीज जो आप कर सकते हैं (आईआईआरसी, अभी जांच नहीं कर सकता) अच्छे पुराने प्रिंट स्टेटमेंट का उपयोग करना है, जिसका आउटपुट डब्ल्यूबी के कंसोल में दिखाई देगा। व्यक्तिगत रूप से, मुझे शायद ही कभी इस उद्देश्य के लिए डीबगर की आवश्यकता महसूस होती है (लोड होने पर पैकेज डीबग करना)
2 संपादित करें
प्रश्न में संपादन के जवाब में:
परिभाषाओं के क्रम के बारे में:हाँ, आप यह कर सकते हैं, और यह इस विशेष समस्या को हल करता है। लेकिन, आम तौर पर, यह मजबूत नहीं है, और मैं इसे एक अच्छी सामान्य विधि नहीं मानूंगा। किसी मामले के लिए एक निश्चित सलाह देना कठिन है, क्योंकि यह अपने संदर्भ से थोड़ा हटकर है, लेकिन मुझे ऐसा लगता है कि UpValues
का उपयोग यहाँ अनुचित है। यदि यह त्रुटि-प्रबंधन के लिए किया जाता है, तो अन्य तरीके
UpValues
. का उपयोग किए बिना इसे करने के लिए .
आम तौर पर, UpValues
किसी फ़ंक्शन को ओवरलोड होने के कारण किसी भी नियम को जोड़े बिना, किसी फ़ंक्शन को सुरक्षित तरीके से ओवरलोड करने के लिए सबसे अधिक उपयोग किया जाता है। एक सलाह है कि UpValues
. को जोड़ने से बचें शीर्षों के साथ जिनमें DownValues
. भी हैं और मूल्यांकन कर सकते हैं - ऐसा करने से आप मूल्यांकनकर्ता के साथ एक खेल खेलना शुरू करते हैं, और अंततः हार जाएंगे। UpValues
attach अटैच करना सबसे सुरक्षित है प्रतीकों (सिर, कंटेनर) को निष्क्रिय करने के लिए, जो अक्सर उन वस्तुओं के "प्रकार" का प्रतिनिधित्व करते हैं जिन पर आप किसी दिए गए फ़ंक्शन को अधिभारित करना चाहते हैं।
HoldPattern
. की उपस्थिति पर मेरी टिप्पणी के संबंध में खराब डिजाइन को दर्शाता है। निश्चित रूप से हैं HoldPattern
. के लिए वैध उपयोग , जैसे यह (कुछ हद तक कृत्रिम) एक:
In[25]:=
Clear[ff,a,b,c];
ff[HoldPattern[Plus[x__]]]:={x};
ff[a+b+c]
Out[27]= {a,b,c}
यहाँ यह उचित है क्योंकि कई मामलों में Plus
अमूल्यांकित रहता है, और अपने अमूल्यांकित रूप में उपयोगी है - क्योंकि कोई यह अनुमान लगा सकता है कि यह एक योग का प्रतिनिधित्व करता है। हमें चाहिए HoldPattern
यहाँ रास्ते के कारण Plus
एक तर्क पर परिभाषित किया गया है, और क्योंकि परिभाषा के दौरान एक पैटर्न एक एकल तर्क होता है (भले ही यह आम तौर पर कई तर्कों का वर्णन करता है)। इसलिए, हम HoldPattern
. का उपयोग करते हैं यहां पैटर्न को सामान्य तर्क के रूप में मानने से रोकने के लिए, लेकिन यह Plus
के लिए इच्छित उपयोग के मामलों से अधिकतर अलग है . जब भी ऐसा होता है (हमें यकीन है कि परिभाषा इच्छित उपयोग के मामलों के लिए ठीक काम करेगी), HoldPattern
ठीक है। ध्यान दें b.t.w., कि यह उदाहरण भी नाजुक है:
In[28]:= ff[Plus[a]]
Out[28]= ff[a]
यह अभी भी ज्यादातर ठीक है इसका कारण यह है कि आम तौर पर हम Plus
. का उपयोग नहीं करते हैं एक ही तर्क पर।
लेकिन, मामलों का एक दूसरा समूह है, जहां आमतौर पर दिए गए तर्कों की संरचना परिभाषा के लिए उपयोग किए जाने वाले पैटर्न की संरचना के समान होती है। इस मामले में, असाइनमेंट के दौरान पैटर्न मूल्यांकन इंगित करता है कि फ़ंक्शन कॉल के दौरान वास्तविक तर्कों के साथ वही मूल्यांकन होगा। आपका उपयोग इस श्रेणी में आता है। एक डिजाइन दोष के लिए मेरी टिप्पणी ऐसे मामलों के लिए थी - आप पैटर्न को मूल्यांकन करने से रोक सकते हैं, लेकिन आपको यह काम करने के लिए तर्कों को मूल्यांकन करने से भी रोकना होगा। और पूरी तरह से मूल्यांकन नहीं की गई अभिव्यक्ति के खिलाफ पैटर्न-मिलान नाजुक है। साथ ही, फ़ंक्शन को तर्कों के लिए कुछ अतिरिक्त शर्तों (जो टाइप-चेक कर सकता है उससे परे) को कभी भी ग्रहण नहीं करना चाहिए।