2011-12-04 11 views
7

Set के लिए उपयोग संदेश हमें याद दिलाता है कि एकाधिक प्रविष्टियों को आसानी से दो सूचियों के बिना दो सूचियों के बिना बनाया जा सकता है। उदाहरण के लिए:स्थानीयकृत चर (जैसे स्थिरांक) उत्पन्न करने में त्रुटि

Remove[x1, x2, y1, y2, z1, z2]; 
{x1, x2} = {a, b} 

काम और रिटर्न निष्पादित करता है:

{a, b} 

Thread, आमतौर पर नियमों की सूची तैयार करने के लिए इस्तेमाल किया, यह भी स्पष्ट रूप से कहा जा सकता है एक ही परिणाम प्राप्त करने के लिए:

Thread[{y1, y2} = {a, b}] 
Thread[{z1, z2} -> {a, b}] 

देता है:

{a, b} 
{z1 -> a, z2 -> b} 

हालांकि, स्थानीयकृत स्थिरांक उत्पन्न करने के लिए इस दृष्टिकोण को नियोजित करने से एक त्रुटि उत्पन्न होती है।

Remove[f]; 
f[x_] := 
With[{{x1, x2} = {a, b}}, 
    x + x1 + x2 
    ] 
f[z] 

त्रुटि संदेश: इस तुच्छ उदाहरण समारोह पर विचार करें

With::lvset: "Local variable specification {{x1,x2}={a,b}} contains 
{x1,x2}={a,b}, which is an assignment to {x1,x2}; only assignments 
to symbols are allowed." 

त्रुटि संदेश प्रलेखन (ref/message/With/lvw) 'अधिक जानकारी' अनुभाग है कि, "यह संदेश उत्पन्न होती है जब में कहते हैं साथ पहला तत्व प्रतीक पर असाइनमेंट की सूची नहीं है। " इस स्पष्टीकरण को देखते हुए, मैं मैकेनिक्स को समझता हूं कि मेरा असाइनमेंट क्यों विफल हुआ। फिर भी, मैं परेशान हूं और सोच रहा हूं कि क्या यह डब्लूआरआई द्वारा आवश्यक प्रतिबंध है, या मामूली डिज़ाइन निरीक्षण की सूचना दी जानी चाहिए।

किसी को भी इस व्यवहार पर कुछ प्रकाश डाला और/या एक समाधान की पेशकश कर सकते हैं:

तो यहाँ मेरे सवाल है? मैंने भाग्य के बिना Evaluation को मजबूर करने की कोशिश करने के साथ प्रयोग किया, और मुझे यकीन नहीं है कि और क्या प्रयास करना है।

+1

मैं अक्सर ऐसे डिज़ाइन विकल्पों पर विचार करता हूं, और मैं कभी-कभी ऐसे प्रश्न पोस्ट करता हूं। दुर्भाग्य से यह दुर्लभ है कि ऐसी चीजों को समझाया गया है। मैंने खुद को इस तथ्य से दबदबा किया है कि/ब्लॉक/मॉड्यूल बस अलग-अलग काम करता है, और इनके पहले तर्क में 'सेट' वास्तव में 'सेट' ऑपरेशन नहीं कर रहा है बल्कि इसके बजाय वाक्यविन्यास है। –

+0

त्रुटि संदेश प्रलेखन (मेरे क्यू के अंत की तरफ उद्धृत भाग) के पढ़ने से मुझे ऐसा लगता है कि वर्तमान व्यवहार को चलाने के लिए कुछ सरल पैटर्न है --- यानी, सिर सूची वाले पैटर्न को स्वीकार करना, जिसमें केवल तत्व जो MatchQ जैसे कुछ के लिए सत्य का मूल्यांकन करते हैं [होल्ड [सेट [एक्स, 1]], [सेट [Symbol_, _]]] दबाएं। यदि ऐसा है, तो कम से कम मेरी मायोपिक छोटी दुनिया में, पैटर्न मिलान/परीक्षण को ट्विक करने के लिए संभव लगता है कि मैं जिस व्यवहार की तलाश करता हूं, और यह कि सेट पर प्रलेखन को इंगित करना चाहिए (एक वैध रूप के रूप में) असाइनमेंट का)। – telefunkenvf14

+0

मैं असहमत नहीं हूं, लेकिन मुझे उस परिवर्तन को प्रभावित करने का कोई तरीका नहीं है। –

उत्तर

11

आप जो अनुरोध करते हैं वह मुश्किल है। यह मैक्रोज़ के लिए एक नौकरी है, जैसा कि पहले से ही दूसरों द्वारा उजागर किया गया है। मैं एक अलग संभावना का पता लगाऊंगा - एक ही प्रतीक का उपयोग करने के लिए, लेकिन उस कोड के चारों ओर कुछ रैपर डालें जिन्हें आप लिखना चाहते हैं। इस तकनीक का लाभ यह है कि कोड रन-टाइम (जैसा कि अन्य उत्तरों में) के बजाए "लेक्सिकली" और "कंपाइल-टाइम" में बदल दिया गया है। यह आम तौर पर डीबग करने के लिए तेज़ और आसान दोनों होता है।

Clear[expandWith]; 
expandWith[heldCode_Hold] := 
Module[{with}, 
    heldCode /. With -> with //. { 
     HoldPattern[with[{{} = {}, rest___}, body_]] :> 
       with[{rest}, body], 
     HoldPattern[ 
     with[{ 
      Set[{var_Symbol, otherVars___Symbol}, {val_, otherVals___}], rest___}, 
      body_]] :> 
       with[{{otherVars} = {otherVals}, var = val, rest}, body] 
    } /. with -> With] 

ध्यान दें कि यह रखे हुए कोड पर चल रही है:

तो, यहाँ एक समारोह जो अपने प्रस्तावित वाक्य रचना के साथ With परिणत हो गया है। इसका लाभ यह है कि हमें संभव मूल्यांकन के बारे में चिंता करने की ज़रूरत नहीं है, न तो शुरुआत में और न ही expandWith समाप्त हो गया है। यहां बताया गया है कि यह कैसे काम करता है:

In[46]:= [email protected][With[{{x1,x2,x3}={a,b,c}},x+x1+x2+x3]] 
Out[46]= Hold[With[{x3=c,x2=b,x1=a},x+x1+x2+x3]] 

हालांकि, इसका उपयोग करने के लिए बहुत सुविधाजनक नहीं है।यहाँ इस आसान बनाने के लिए एक सुविधा समारोह है:

In[47]:= [email protected][{{x1,x2}={a,b}},x+x1+x2] 
Out[47]= a+b+x 

तो, विस्तार कोड में होती हैं, बस लपेट ew इसके चारों ओर बनाने के लिए:

ew = Function[code, [email protected]@[email protected], HoldAll] 

हम यह अब के रूप में उपयोग कर सकते हैं।

Remove[f]; 
ew[f[x_] := With[{{x1, x2} = {a, b}}, x + x1 + x2]] 

अब हम जांच करें और देखें कि क्या हम मिल एक विस्तारित परिभाषा है:

?f 
Global`f 
f[x_]:=With[{x2=b,x1=a},x+x1+x2] 

इस दृष्टिकोण का लाभ यह है कि आप एक के आसपास ew लपेट कर सकते हैं यहाँ समारोह की परिभाषा के लिए अपने मामले है आपके कोड का मनमाने ढंग से बड़ा हिस्सा। क्या होता है कि पहला, विस्तारित कोड उस से उत्पन्न होता है, जैसे कि आप इसे स्वयं लिखेंगे, और फिर वह कोड निष्पादित हो जाता है। फ़ंक्शन की परिभाषाओं के मामले में, जैसे f ऊपर, हम यह कर सकते हैं कि कोड जनरेशन "संकलन-समय" पर होता है, इसलिए जब आप फ़ंक्शन को बाद में करते हैं तो आप किसी भी रन-टाइम ओवरहेड से बचते हैं, जो फ़ंक्शन को अक्सर कहा जाता है, तो यह पर्याप्त हो सकता है।

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

संपादित

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

Clear[expandWithAlt]; 
expandWithAlt[heldCode_Hold] := 
Module[{myHold}, 
    SetAttributes[myHold, HoldAll]; 
    heldCode //. HoldPattern[With[{Set[{vars__}, {vals__}]}, body_]] :> 
    With[{eval = 
       (Thread[Unevaluated[Hold[vars] = Hold[vals]], Hold] /. 
        Hold[decl___] :> myHold[With[{decl}, body]])}, 
     eval /; True] //. myHold[x_] :> x] 

मुझे यह पहले की तुलना में काफी जटिल लगता है।

+0

अद्भुत, लियोनिद! –

+0

यह 'साथ' का उपयोग करने के आदर्श के करीब आता है, फिर भी डिफ़ॉल्ट कार्यक्षमता को संशोधित नहीं करता है। आसान +1। –

+0

क्या आपको लगता है कि [Gayley-Villegas] (http://stackoverflow.com/a/5149656/421225) अंतर्निहित 'साथ' के प्रकार का संशोधन करना संभव है? – Simon

6

ट्यूटोरियल "LocalConstants" कहते हैं

रास्ता साथ [{x = सबस्क्रिप्ट [x, 0], ...}, शरीर] काम करता है शरीर लेते हैं, और एक्स के हर घटना को बदलने के लिए है , आदि में सदस्यता [x, 0], आदि द्वारा आप के सामान्यीकरण के रूप में सोच सकते हैं। ऑपरेटर, अन्य अभिव्यक्तियों के बजाय गणित कोड के लिए आवेदन के लिए उपयुक्त है।

इस व्याख्या का जिक्र करते हुए यह स्पष्ट लगता है कि कुछ

तरह
x + x1 + x2 /. {x1, x2} -> {a, b} 

के रूप में यह में उम्मीद की जा सकती अंकन के साथ काम नहीं करेगा।

मान लीजिए कि आप वास्तव में इसके आसपास हैक करना चाहते हैं। With[] विशेषता होल्डएल है, इसलिए जो कुछ भी आप पहले पैरामीटर के रूप में देते हैं उसका मूल्यांकन नहीं किया जाता है। ऐसे वेक्टर-असाइनमेंट काम करने के लिए आपको

With[{x1=a, x2=b}, ...] 

वेक्टर-नोटेशन से बनाना होगा।दुर्भाग्यवश,

Thread[{a, b} = {1, 2}] 

काम नहीं करता है क्योंकि थ्रेड के लिए तर्क नहीं है और थ्रेड कुछ भी करने से पहले असाइनमेंट का मूल्यांकन किया जाता है।

इस

SetAttributes[myThread, HoldFirst]; 
myThread[Set[a_, b_]] := mySet @@@ Transpose[{a, b}] 

देता

In[31]:= myThread[{a, b, c} = {1, 2, 3}] 
Out[31]= {mySet[a, 1], mySet[b, 2], mySet[c, 3]} 

क्या पहली बार में होनहार लग रहा है ठीक करने देता है, थोड़ा-सा दूर समस्या ले जाया गया। With[] में इसका उपयोग करने के लिए आपको रीयल सेट के साथ माइसेट को किसी बिंदु पर बदलना होगा। वास्तव में तो, With[] सूची {एक = 1, = 2, सी = 3 ख} लेकिन, मूल्यांकन किया जाना है, क्योंकि यह है, सभी कार्य का परिणाम

In[32]:= With[ 
Evaluate[myThread[{a, b, c} = {1, 2, 3}] /. mySet :> Set], a + b + c] 

During evaluation of In[32]:= With::lvw: Local 
variable specification {1,2,3} contains 1, which is not an assignment to a symbol. >> 

Out[32]= With[{1, 2, 3}, a + b + c] 

वहाँ नहीं आसान तरीका प्रतीत हो रहा है नहीं देखता इसके आस-पास और यहां एक दूसरा प्रश्न है: यदि इस प्रतिबंध के आसपास कोई रास्ता है, तो क्या यह उतना तेज होगा जितना कि होगा या हम मॉड्यूल की तुलना में गति लाभ खो देंगे? और यदि गति इतनी महत्वपूर्ण नहीं है, तो मॉड्यूल या ब्लॉक का उपयोग क्यों न करें?

+0

halirutan, आपका स्वागत है StackOverflow करने के लिए। –

+0

आपका अंतिम अनुच्छेद यह सुझाव देता है कि यह समस्या 'मॉड्यूल' या 'ब्लॉक' को प्रभावित नहीं करती है, लेकिन यह करता है। या, क्या आप कह रहे हैं कि 'मॉड्यूल' या 'ब्लॉक' के लिए कोई कामकाज है जो 'साथ' पर काम नहीं करता है? –

+2

@ एमआर।मॉड्यूल और ब्लॉक में विज़ार्ड आप कम से कम मॉड्यूल [{ए, बी, सी}, {ए, बी, सी} = {1, 2, 3} कर सकते हैं; ए + बी + सी] जो साथ काम नहीं करता है। – halirutan

7

मुश्किल मुद्दा सेट अपरिवर्तित के पहले तर्क को रखना है। यहाँ मेरी सुझाव (बेशक सुधार के लिए खुला) है:

SetAttributes[myWith, HoldAll]; 
    myWith[{s : Set[a_List, b_List]}, body_] := 
    [email protected] 
     Hold[With][ 
     Table[Hold[Set][Extract[Hold[s], {1, 1, i}, Hold], 
     Extract[Hold[s], {1, 2, i}]], {i, [email protected]}], [email protected]] 
    x1 = 12; 
    Remove[f]; 
    f[x_] := myWith[{{x1, x2} = {a, b}}, x + x1 + x2] 
    f[z] 

परिणाम

a+b+z 

halirutan से प्रेरित होकर नीचे मैं उसका समाधान लगता है, थोड़ा और अधिक सुरक्षित रूप से बनाया है, इसके बाद के संस्करण के बराबर है:

SetAttributes[myWith, HoldAll]; 
myWith[{Set[a : {__Symbol}, b_List]} /; Length[a] == Length[b], 
    body_] := 
[email protected] 
    Hold[With][ 
    Replace[Thread[Hold[a, b]], Hold[x_, y_] :> Hold[Set[x, y]], 1], 
    [email protected]] 
+0

अच्छा! 'साथ' पकड़ना महत्वपूर्ण बात प्रतीत होता है। निम्नलिखित एक ही चाल का उपयोग करता है: 'f [x_] = रिलीजहोल्ड @ [ फ़्लैटन @ {({x1, x2} -> {a, b} // थ्रेड)/के साथ रखें। (नियम [q_, r_] -> होल्डफॉर्म @ सेट [क्यू, आर])}, x + x1 + x2] 'x1 = 5 का उपयोग करना; एफ [जेड] 'ए + बी + जेड 'देता है। – kglr

+0

यदि आप पहले तर्क को {{s: सेट [a_List, b_List] 'के साथ सेट करते हैं: (सेट | नियम) [a_List, b_List] 'कुछ और बदले बिना, तो कोई इसे' g [x_] : = myWith [{{x1, x2) -> {a, b}}, x + x1 + x2] 'नियमों का उपयोग करके और' एच [x _]: = myWith [{{x1, x2) = {a, b }}, x + x1 + x2] 'स्थानीय चर के प्रारंभ के लिए असाइनमेंट का उपयोग करना। – kglr

+0

अच्छी चीजें रॉल्फ! क्षमा करें मैं टिप्पणी करने और वोट करने के लिए अभी वापस आया था। +1। –

3

आप 100 अक्षरों से Rolfs समाधान छोटा करने के लिए इस्तेमाल कर सकते हैं पक्षांतरित:

SetAttributes[myWith, HoldAll]; 
myWith[{Set[a_List, b_List]}, body_] := 
ReleaseHold[Hold[With][Hold[Set[#1, #2]] & @@@ Transpose[{a, b}], 
    [email protected] 
    ]] 

@ हेइक, उपर्युक्त ब्रेक यदि या तो चर पहले से ही एक मान है। इसके बारे में क्या:

SetAttributes[myWith, HoldAll]; 
myWith[{Set[a_List, b_List]}, body_] := 
[email protected] 
    Hold[With][Thread[Hold[a, b]] /. Hold[p__] :> Hold[Set[p]], 
    [email protected]] 
+1

यह तोड़ता है जब 'ए' में चरों में से एक को पहले सेट किया गया है, उदा। 'ए = 3; myWith [{{a, b, c} = {1, 2, 3}}, एक^2 + बी] 'एक त्रुटि देता है, लेकिन यह आसानी से'ब्लॉक [{a}, ...] डालकर ठीक किया जाता है। 'myWith' के दाएं हाथ के चारों ओर। – Heike

+0

मैंने उत्तर पोस्ट करने के बाद इसे देखा। – halirutan