2011-12-15 26 views
7

द्वारा पैरामीटर प्रदान करने के इस सवाल एम में संदर्भ द्वारा पारित करने के विषय पर है (मेरा एक संबंधित सवाल यहाँ है simple question on passing data between functions)एक struct का उपयोग संदर्भ

जब मैं संदर्भ द्वारा चीजों को पारित करने के लिए एक रास्ता खोजने के लिए कोशिश कर रहा था Unevaluted[] या HoldFirst[] का उपयोग किए बिना, मैंने गलती से इस विधि को मारा और यह वास्तव में मेरे लिए अच्छा काम कर रहा है, भले ही मुझे यह समझ में नहीं आता कि यह कैसे काम करता है और इसका उपयोग करने के किसी भी छिपे जोखिम। इसलिए मैं इसे विशेषज्ञों को यहां दिखाना चाहता हूं और पूछता हूं कि क्या उन्हें लगता है कि यह उपयोग करना सुरक्षित है (मेरे पास बहुत बड़ा डेमो है और उन्हें प्रबंधित करने में सहायता के लिए विभिन्न structs की संख्या में पैरामीटर पैकेज करने की आवश्यकता है, और इस तरह मैंने इसे पाया विधि जब मैं चीजों की कोशिश कर रहा था)।

यहाँ विधि है: सबसे पहले हम जानते हैं कि एक का पालन नहीं कर लिख सकते हैं:

Remove[p] 
foo[p_] := Module[{u}, 
    u = Table[99, {10}]; 
    p = u 
    ]; 

p = 0; 
foo[p]; 

एक 'पी' को अद्यतन करने के लिए ऊपर दिए गए बनने के लिए कॉल करने के लिए बदलने के लिए है जिस तरह से

foo[[email protected]]; 

या foo[] को HoldFirst के साथ परिभाषित करके।

लेकिन यहाँ, जिस तरह से मैंने पाया है, जो संदर्भ द्वारा पारित करता है इनमें से किसी के बिना:

मैं एक struct (मैं अब इस वैसे भी करते हैं) में सभी मापदंडों रखा, और struct गुजरती हैं, और फिर एक foo[] अंदर struct के क्षेत्र अद्यतन कर सकते हैं और अद्यतन रास्ता समारोह कॉल से वापस में परिलक्षित होगा:

Remove[parms] 
foo[parms_] := Module[{u}, 
    u = Table[99, {10}]; 
    parms["p"] = u 
    ]; 

parms["p"] = 0; 
foo[parms]; 

अब, parms["p"] नई सूची {99, 99, 99, 99, 99, 99, 99, 99, 99, 99}

एस निहित ओ, parmsfoo[] के अंदर 0wrपास करने के लिए एम को बताने के बिना foo[] के अंदर ओवरराइट/अपडेट किया गया था!

मैंने अपने कार्यक्रम में यह कोशिश की, और मुझे कोई अजीब दुष्प्रभाव नहीं दिख रहा है। सीडीएफ को कोई त्रुटि के साथ ठीक से अद्यतन किया गया था। मुझे नहीं पता कि यह कैसे काम करता है, क्या एम parms के अंदर सभी क्षेत्रों को ग्लोबल के रूप में मान सकता है?

लेकिन किसी भी मामले में, मैं इस से खुश हूं क्योंकि यह मुझे अपने कई पैरामीटर को structs में पैकेज करने का एक तरीका प्रदान करता है, और साथ ही मैं संरचना के कार्यों के अंदर अद्यतन करने में सक्षम हूं।

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

बीटीडब्ल्यू, मैंने अब तक देखा है सबसे अच्छा स्ट्रक्चर इम्यूलेशन इस धागे here के अंत में लियोनीड शिफ्रिन द्वारा पोस्ट किया गया था लेकिन दुर्भाग्य से मैं इसे अपने डेमो में उपयोग नहीं कर सका क्योंकि यह डेमो में अनुमति नहीं है CDF।

धन्यवाद

अद्यतन: Btw, इस नीचे मैं क्या सोचता कैसे एम इस संभालती है।यह मेरा अनुमान है: मुझे लगता है कि param किसी प्रकार की लुकअप टेबल है, और इसके फ़ील्ड्स का उपयोग सिर्फ एक इंडेक्स के रूप में किया जाता है (हैश टेबल हो सकता है?) फिर param["p1"] इसमें पता होगा (मूल्य नहीं) के ढेर में एक स्थान का जहां param["p1"] का वास्तविक मूल्य रहता है।

कुछ इस तरह:

enter image description here

तो, जब param गुजर, तो समारोह foo[], जब param["p1"]=u टाइपिंग के अंदर यह वर्तमान स्मृति बताया "p1" द्वारा अप करने के लिए मुक्त किया जा करने के लिए कारण होगा, और फिर एक ढेर से आवंटित नई मेमोरी, और इसमें u का मान कॉपी किया गया है।

और इसलिए, वापस लौटने पर, यही कारण है कि हम param["p1"] की सामग्री को बदल चुके हैं। लेकिन वास्तव में क्या बदल गया, स्मृति की सामग्री उस पते से इंगित की जा रही है जो param["p1"] दर्शाती है।

(वहाँ एक नाम है, जो "p1" है, और एक पते क्षेत्र है, जो सामग्री है कि नाम "p1" का प्रतिनिधित्व करता है ओर इशारा करता है) लेकिन तब इसका मतलब है, कि पता ही है, जो "p1" का प्रतिनिधित्व करता है बदला है, लेकिन देखने नाम स्वयं (जो "पी 1" है) नहीं बदला।

इसलिए, जैसा कि नाम स्वयं नहीं बदला गया था, होल्डफर्स्ट का उपयोग करने की कोई आवश्यकता नहीं थी, भले ही इस नाम का प्रतिनिधित्व करने वाले डेटा के आधार पर डेटा को संशोधित किया गया हो?

अद्यतन:

इस विधि में एक छोटी सी गड़बड़ है, लेकिन यह एक बड़ी बात यह आस-पास काम करने के लिए नहीं है: जब इस अनुक्रमित वस्तु विधि का उपयोग कर बातें गुजर, यह पता चला है कि एक नहीं कर सकते वस्तु का हिस्सा संशोधित करें। उदाहरण के लिए, इस नीचे काम नहीं करता:

foo[param_] := Module[{}, 
    param["u"][[3]] = 99 (*trying to update PART of u *) 
    ]; 

param["u"] = Table[0, {5}]; 
foo[param]; 

उपरोक्त त्रुटि

Set::setps: "param[u] in the part assignment is not a symbol" 

देता है लेकिन वैकल्पिक हल आसान है। तब स्थानीय प्रतिलिपि का (भाग) को अद्यतन पूरे क्षेत्र है कि एक इसका हिस्सा अद्यतन करने के लिए चाहता है की स्थानीय प्रतिलिपि बनाने के लिए,, फिर वापस क्षेत्र के लिए प्रति लिखते हैं, इस

foo[param_] := Module[{u = param["u"]}, (* copy the whole field *) 
    u[[3]] = 99; (*update local copy *) 
    param["u"] = u (*now update the field, ok *) 
    ]; 

param["u"] = Table[0, {5}]; 
foo[param]; 

खैर की तरह। यदि कोई क्षेत्र के हिस्से को अपडेट कर सकता है तो बेहतर होगा, इसलिए 'विशेष' हैंडलिंग की आवश्यकता नहीं होगी। लेकिन कम से कम काम इतना बुरा नहीं है।

अद्यतन पूर्णता के लिए, मैंने सोचा कि मैं अनुक्रमित वस्तुओं और आसपास के काम का उपयोग करने के बारे में एक और छोटी बात का उल्लेख करता हूं।

मैं

param[u] = {1, 2, 3} 
param[u][[1 ;; -1]] 

कौन सा {1,2,3} रिटर्न की उम्मीद के रूप में लिखा था।

तब मैंने पाया कि param[u] के बजाय मैं [email protected] का उपयोग कर सकता हूं, जिसने वास्तव में बहुत से ठोस ब्रैकेट्स को सिरदर्द देने के लिए शुरू कर दिया है।

लेकिन तब

जब मैं टाइप किया
[email protected][[1 ;; -1]] 

पहले की तरह ही जवाब वापस पाने के लिए उम्मीद कर रहा, ऐसा नहीं किया। एक एक त्रुटि हो जाता है, (मुझे लगता है कि मैं जानता हूँ कि क्यों, ऑपरेटर पूर्वता मुद्दा, लेकिन उस समय अब ​​नहीं है), सिर्फ इतना कहना है कि वैकल्पिक हल के लिए आसान है चाहता था, या तो एक param[u][[1 ;; -1]] का उपयोग करें या ([email protected])[[1 ;; -1]]

उपयोग कर सकते हैं मुझे पसंद है ([email protected])[[1 ;; -1]] और, इसलिए मैं अब अनुक्रमित वस्तुओं के अंदर सूचियों तक पहुंचने के लिए उपयोग कर रहा हूं।

नोटेशन [email protected] उतना करीब है जितना मैं मानक रिकॉर्ड नोटेशन प्राप्त कर सकता हूं जो param.u है इसलिए अब मैं अनुक्रमित वस्तुओं के साथ खुश हूं, और ऐसा लगता है कि यह वास्तव में अच्छी तरह से काम कर रहा है। देखने के लिए कुछ मामूली चीज़ों को देखने के लिए।

+0

इस प्रश्न में बहुत कुछ चल रहा है। क्या आपके पास एक विशिष्ट चीज है जिसे आप प्राप्त करने का प्रयास कर रहे हैं? –

+0

@ माइकबेंटगेई, मैं मूल रूप से यह पूछ रहा हूं कि इसे कैसे कार्यान्वित किया जाता है, और यह क्यों काम करता है क्योंकि एक कार्य के अंदर पैरामीटर को संशोधित करने में सक्षम है, जिसे एम में अनुमति नहीं है, क्योंकि एम में सामान्य पासिंग मूल्य से है। लेकिन यहां यह हो रहा है और होल्डफर्स्ट का उपयोग किए बिना और अनियंत्रित उपयोग किए बिना। इसे कैसे समझाओ? – Nasser

+0

नासर, कृपया मेरा जवाब पढ़ें और मुझे बताएं कि अस्पष्ट क्या है। –

उत्तर

5

मैं निम्न स्तर के डेटा संरचनाओं के सवाल का जवाब नहीं दे रहा हूं क्योंकि मैं ऐसा करने के लिए योग्य नहीं हूं।

आप "indexed objects" बना रहे हैं और सूचकांक के रूप में अपरिवर्तनीय तारों का उपयोग कर रहे हैं। आम तौर पर मुझे विश्वास है कि ये हैश टेबल के समान हैं।

अपने कोड उदाहरण लें तो हमें foo के तर्क के लिए एक अनूठा नाम का उपयोग करके एक संभव अस्पष्टता को दूर करते हैं:

Remove[parms, foo] 

foo[thing_] := 
    Module[{u}, 
    u = Table[99, {10}]; 
    thing["p"] = u 
    ]; 

parms["p"] = 0; 
foo[parms]; 

parms["p"] 

DownValues[parms] 
{HoldPattern[parms["p"]] :> {99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}

यह दिखाता है कि डेटा उच्च स्तर मेथेमेटिका के मामले में संग्रहीत किया जाता है संरचनाएं।

parms एक वैश्विक प्रतीक है। जैसा कि आपने देखा है, इसे बिना किसी घटना के सुरक्षित रूप से "पास" किया जा सकता है, क्योंकि यह OwnValues के बिना सिर्फ एक प्रतीक है और मूल्यांकन होने पर कुछ भी ट्रिगर नहीं होता है। यह बिल्कुल foo लिखने/मूल्यांकन करने जैसा ही है।

foo[thing_] := ... में होने वाला प्रतिस्थापन With के समान है। अगर हम लिखें:

With[{thing = parms}, thing[x]] 

thingthing[x] में parmsthing[x] से पहले मूल्यांकन करता है साथ बदल दिया है। इसी तरह, ऊपर दिए गए कोड में हमें parms["p"] = uthing["p"] या Set मूल्यांकन से पहले मिलता है। उस समय, HoldFirstSet की विशेषता लेती है, और आप जो चाहते हैं उसे प्राप्त करते हैं।

चूंकि आप अपनी अनुक्रमणिका के रूप में एक अपरिवर्तनीय स्ट्रिंग का उपयोग कर रहे हैं, इसलिए यह बदलने का खतरा नहीं है। जब तक आप parms जैसे गैर-स्थानीयकृत प्रतीकों को संभालने के बारे में जानते हैं, तब भी इस विधि का उपयोग करने में कोई नया खतरा नहीं है।

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