2011-06-20 13 views
5

बच सकता है मैं कोड के इस बिट है:एफ # कोटेशन: चर गुंजाइश

let rec h n z = if n = 0 then z 
       else <@ (fun x -> %(h (n - 1) <@ x + %z @>)) n @> 

http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf

में एक MetaOcaml उदाहरण से परिवर्तित पत्र में वहाँ से समझाया गया है कि ऊपर के उदाहरण के साथ निम्न निकलेगा मापदंडों 3 और .<1>. (MetaOcaml अंकन में):

.<(fun x_1 -> (fun x_2 -> (fun x_3 -> x_3 + (x_2 + (x_1 + 1))) 1) 2) 3>. 

आपदेख सकते हैंकी जगह x_1, x_2 आदि से बदल दी गई है क्योंकि x अन्यथा को fun में केवल x का संदर्भ देगा।

लेकिन एफ # में इसकी अनुमति नहीं है। मुझे संकलन-समय त्रुटि मिलती है: "परिवर्तनीय 'x' उद्धरण में बंधे हुए हैं लेकिन एक स्प्लिस्ड अभिव्यक्ति के हिस्से के रूप में उपयोग किया जाता है। इसकी अनुमति नहीं है क्योंकि यह इसके दायरे से बच सकता है।" तो सवाल यह है कि: यह कैसे बदला जा सकता है ताकि यह संकलित हो और मेटाकैम आउटपुट के समान अर्थपूर्ण हो?

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

Tomas' जवाब देने के लिए अद्यतन: मैं वास्तव में नहीं x वैश्विक होना चाहता हूँ, या गुंजाइश से बचने के लिए। लेकिन मैं

let rec h n z = if n = 0 then z 
       else (fun x -> (h (n - 1) (x + z))) n 

के समतुल्य के बराबर है। आपका उत्तर (h 3 <@ 1 @>).Eval() = 4 देता है जहां उपर्युक्त h 3 1 = 7 उत्पन्न करता है। और यहां, मैं जवाब होने के लिए 7 चाहता हूं।

+0

मुझे मेयोकामल नहीं पता, लेकिन ऐसा लगता है कि आप असली एफ # कोड में उद्धरण लैम्ब्डा से एक चर का उपयोग करने की कोशिश कर रहे हैं। कोटेशन वास्तविक एफ # कोड नहीं हैं, और इसी कारण से आप उनका मूल्यांकन भी नहीं कर सकते हैं (LINQ मूल्यांकनकर्ता को छोड़कर, जो सही नहीं है)। –

उत्तर

6

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

open Microsoft.FSharp.Quotations 

let rec h n (z:Expr<int>) = 
    if n = 0 then z     
    else 
    let v = new Var("x", typeof<int>) 
    let ve = Expr.Var(v) 
    Expr.Cast<int> 
     (Expr.Application(Expr.Lambda(v, h (n - 1) <@ %%ve + %z @>), 
          Expr.Value(n))) 

बहरहाल, यह काफी कृत्रिम उदाहरण (MetaOCaml है, जो एफ # में उपलब्ध नहीं है में चर कैप्चरिंग प्रदर्शित करने के लिए) है। यह सिर्फ (2 + (1 + ...)) जैसे अभिव्यक्ति उत्पन्न करता है। आप कुछ इस तरह लिख कर एक ही परिणाम प्राप्त कर सकते हैं:

let rec h n (z:Expr<int>) = 
    if n = 0 then z     
    else h (n - 1) <@ n + %z @> 

या और भी बेहतर:

[ 1 .. 4 ] |> List.fold (fun st n -> <@ n + %st @>) <@ 0 @> 

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

+0

आप एक सक्षम आदमी की तरह लगते हैं :) लेकिन यह पूरी तरह से नहीं है जो मैं चाहता हूं। मैं अपने प्रश्न में पर्याप्त स्पष्ट होने में असफल रहा हूं, इसलिए 2 सेकंड में प्रश्न का एक अद्यतन होगा। –

+0

@lasseespeholt: मैंने 'Var.Global' (जो कि गलत था) के बजाय' नया Var' का उपयोग करने के लिए संस्करण को बदल दिया)। इसे अब प्रत्येक पुनरावृत्ति में एक नया चर घोषित करना चाहिए (उनके पास समान _name_ होगा, लेकिन _different_ चर होगा)। –

+0

@ टोमा धन्यवाद :) अपेक्षित के रूप में काम करता है। हालांकि, मुझे लगता है कि मैं मेटाओकैम पर फॉलबैक करूँगा क्योंकि मैं इसे बहु मंच प्रोग्रामिंग के लिए उपयोग करना चाहता था। –

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