2010-04-28 7 views
7

निम्नलिखित कोड वापस लौटा 14 के रूप में आप उम्मीद थी:शाब्दिक और गतिशील scoping: मॉड्यूल के साथ स्थानीय चर, के साथ, और ब्लॉक

Block[{expr}, 
    expr = 2 z; 
    f[z_] = expr; 
    f[7]] 

लेकिन अगर आप को बदलने कि BlockModule एक करने के लिए तो यह 2*z रिटर्न । यह कोई फर्क नहीं पड़ता कि expr के अलावा अन्य चर क्या हैं। मैंने सोचा कि मैं गणित में मॉड्यूल, ब्लॉक, और साथ ही समझता हूं लेकिन मैं इस उदाहरण में मॉड्यूल और ब्लॉक के बीच व्यवहार में अंतर को समझा नहीं सकता।

संबंधित संसाधन:

पुनश्च एक से

  • अंश Tutorial on Modularity and the Naming of Things:Michael Pilat के लिए धन्यवाद, Davorak, और टी निम्नलिखित के लिए Bill White वह इस अजीबता पर सुगंधित निशान। Davorak स्पष्ट किया और इस मुद्दे को यहाँ के दिल के हो जाता है: Why would Mathematica break normal scoping rules in Module?

  • उत्तर

    6

    मैं भी इससे थोड़ा आश्चर्यचकित था, लेकिन मुझे नहीं लगता कि यह एक बग है।

    In[1]:= Module[{e = Expand[(1 + x)^5]}, Function[x, e]] 
    
    Out[1]= Function[x$, e$1194] 
    
    In[2]:= %[10] 
    
    Out[2]= 1 + 5 x + 10 x^2 + 10 x^3 + 5 x^4 + x^5 
    

    Function: आप reference page for Module में उदाहरण में गहरी देखो, तो नामक भाग संभावित समस्याओं के तहत, वहाँ एक छोटे से टिप्पणी का कहना है कि "चर नेस्टेड कार्यक्षेत्रों में नाम दिया गया है" और निम्न उदाहरण देता है Module की तरह एक और स्कोपिंग निर्माण है, इसलिए के दायरे में आंतरिक रूप से x$ का नाम बदल दिया गया है, जैसा कि आपने Trace के बारे में z के साथ खोजा था।

    अपने Modulef को परिभाषित करने में, Set एक और ऐसे scoping निर्माण है, और इसलिए z जब f एक Module के अंदर परिभाषित किया गया है नाम दिया गया है, लेकिन नहीं, जब यह एक Block अंदर क्या है। Module दस्तावेज़ से कि उदाहरण के सलाह के बाद, आप अपने हिस्से से अपने समारोह के आरएचएस निर्माण नेस्टेड दायरे से शाब्दिक नाम से बचने के लिए कर सकते हैं:

    In[3]:= Clear[f, z] 
    
    In[4]:= Module[{expr}, 
        expr = 2 z; 
        Set @@ {f[z_], expr}; 
        f[7]] 
    
    Out[4]= 14 
    

    HTH!

    +1

    वाह, मैं जो कुछ भी एक सुंदर काम नहीं कहूंगा, लेकिन प्रभावशाली काम यह पता लगा रहा है! – dreeves

    +0

    यही कारण है कि मैं हर दिन SO पर वापस आ जाता हूं। मुझे कुछ एस ** टी :-) सीखता है। – Timo

    +0

    मैं अजीब अल्फा रूपांतरण में लपेटकर एक्सपेर होने के बजाय अप्रत्याशित प्रदर्शन हिट लेता हूं बल्कि असंगत वाक्यविन्यास से निपटता हूं। यहां खेलने के लिए भाषा डिजाइन विचार क्या चल रहे हैं? – Davorak

    2

    आप दोनों भाव पर ट्रेस इस्तेमाल किया है?

    +0

    आह, स्मार्ट! तो मॉड्यूल संस्करण में 'z_' को 'z $ _' में बदल दिया जा रहा है। तो मुझे लगता है कि यह समझाता है लेकिन मुझे अभी भी समझ में नहीं आता कि यह क्यों हो रहा है! शायद मैं उस अजीबता के बारे में पूछने के लिए हालांकि सवाल को अद्यतन करूंगा। – dreeves

    3

    सबसे पहले मुझे लगता है कि आपने यहां एक बग का खुलासा किया है।

    दूसरा मुझे लगता है कि मैं, क्यों यह हो रहा है के लिए कुछ अंतर्दृष्टि प्रदान कर सकते हैं ध्यान में रखते हुए mathematica के आंतरिक भागों की मेरी जानकारी सीमित हैं।

    की तरह एक बयान: च [z_]: = 2 पूर्ण रूप में जेड है:

    SetDelayed[f[Pattern[z, Blank[]]], 2 z] 
    

    यह DownValue [च] करने के लिए सेट:

    {HoldPattern[f[z_]] :> 2 z} 
    

    फिर बाद में जब एक अभिव्यक्ति, च की तरह [2], बाद में निम्नलिखित preformed की जा रही है की तरह कुछ का मूल्यांकन किया जाता है:

    f[2] /. HoldPattern[f[z_]] :> 2 z 
    

    कौन सा 4. करने के लिए मूल्यांकन करेगा अब यह सब पो है ssible क्योंकि पहले कोड ब्लॉक से पैटर्न मिलान [z, खाली []] के साथ पैटर्न मिलान हो रहा है। यह तब भी काम करता है जब आपने बड़े पैमाने पर ज़ेड को सेट किया हो। दूसरे शब्दों में।

    z = 5; 
    f[z_] := 2*z 
    

    फिर भी च के लिए एक ही downvalues ​​पैदा करता है:

    {HoldPattern[f[z_]] :> 2 z} 
    

    यह संभव है क्योंकि पैटर्न HoldFirst गुण है।

    यदि आप मॉड्यूल के अंदर इसका मूल्यांकन करते हैं तो होल्डफ़ास्ट विशेषता पर्याप्त सुरक्षा नहीं है। उदाहरण:

    SetAttributes[tmp, HoldFirst]; 
    Module[{expr}, 
    expr = 2 z; 
    tmp[expr] 
    ] 
    

    आउटपुट:

    tmp[expr$8129] 
    

    मेरा प्रस्ताव है कि कि कि एक स्थानीय चर शामिल किसी नियम में किसी भी पैटर्न उनके पैटर्न चर फिर से लिखा है, क्योंकि HoldFirst गुण मॉड्यूल के चर पुनर्लेखन नियम के लिए प्रतिरक्षा प्रदान नहीं करता है । sym-> प्रतीक [SymbolName [प्रतीक] ~~ "$"]

    Module[{expr}, 
    Hold[z_ -> (z; expr)] 
    ] 
    (*Hold[z$_ -> (z$; expr$1391)]*) 
    

    z एक सरल अल्फा रूपांतरण में शासन के दोनों किनारों पर लिखा जा चुका है।

    नियम एक स्थानीय चर कोई पुनर्लेखन होता नहीं है, तो:

    Module[{expr}, 
    Hold[z_ -> (z)] 
    ] 
    (*Hold[z_ -> z]*) 
    

    बल्कि फिर अगर एक स्थानीय चर एक नियम चर ऊपर कंबल नियम लागू किया जाता है से मेल खाता देखने के लिए खोज।

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

    यह ब्लॉक में नहीं होता है क्योंकि ब्लॉक किसी स्थानीय चर को फिर से लिखता नहीं है।

    कोई अन्य विचार? कोई भी मेरे तर्क में कोई छेद देखता है?

    +0

    बहुत बहुत धन्यवाद, Davorak। ऐसा लगता है कि आप और माइकल पिलैट एक ही मुद्दे पर आ रहे हैं, है ना? – dreeves

    +0

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

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