2013-04-16 5 views
15

एफ # कल्पना (§6.5.7 देखें) के अनुसार, छोरों के लिए सरल पूर्णांक (int उर्फ ​​int32 उर्फ ​​System.Int32) की सीमा start और stop, उदा से घिरा रहे हैंलूप अभिव्यक्तियों के लिए पूर्णांक सीमाओं तक सीमित क्यों हैं?

for i = start to stop do 
    // do sth. 

मुझे आश्चर्य है कि क्यों पाश के लिए इस प्रकार के यात्रा सीमा int32 होना भी आवश्यक है। uint32 क्यों न दें? int64? bigint?

मुझे पता है कि अनुक्रम पुनरावृत्ति अभिव्यक्ति (for ... in ...) मनमाने ढंग से अनुक्रमों पर फिर से शुरू हो सकती है; हालांकि, इसे एक पुनरावर्तक आवंटित करने और MoveNext और Current पर कॉल करने की आवश्यकता होती है और सादे लूप की तुलना में काफी कम कुशल नहीं हो सकता है (वृद्धि काउंटर, तुलना, conditonal कूद)। कि बचने के लिए आप, while और एक मैन्युअल रूप से बढ़ाने पाश काउंटर का उपयोग कर के साथ फंस रहे हैं ...

अजीब पर्याप्त

एफ # , अगर for अभिव्यक्ति एक दृश्य अभिव्यक्ति में लपेटा जाता है, गैर int32 पाश सीमा की अनुमति नहीं है जैसे

seq { for i = 0I to 10I do 
     printfn "%A" i } 

तो, मुझे लगता है कि सवाल यह है: वहाँ केवल छोरों के लिए int32 अनुमति देने के लिए एक विशेष कारण है? और seq अभिव्यक्तियों में लिपटे for लूप पर यह प्रतिबंध क्यों लागू नहीं होता है?

+0

सामान्य में, नेट ढांचे 'int' एक सामान्य प्रयोजन पूर्णांक के रूप में उपयोग करता है, संख्यात्मक अनुक्रमण परिदृश्यों के सभी प्रकार में इसके उपयोग भी शामिल है। उदाहरण: http://msdn.microsoft.com/en-us/library/system.array.indexof(v=vs.71).aspx। काउंटर उदाहरण: http://msdn.microsoft.com/en-us/library/system.io.filestream.position.aspx, जो लंबे समय तक उपयोग करता है। –

+4

एफ # कार्यात्मक प्रोग्रामिंग को प्रोत्साहित करता है और इसलिए पूर्ण अनिवार्य समर्थन से कम रोकता है (उदाहरण के लिए, 'ब्रेक'/'रिटर्न' की कमी)। एक गणना अभिव्यक्ति 'के लिए' एक विधि कॉल से वंचित है, जो एक लूप की तरह अनिवार्य रूप से अनिवार्य नहीं है, और इसलिए समान सीमाएं नहीं हैं। हालांकि मैं रहस्य को समझ सकता हूं। +1 – Daniel

+0

@ डैनियल +1 "एक गणना अभिव्यक्ति के भीतर एक विधि कॉल के लिए desugared है"। समझा; वास्तव में 'seq {के लिए जेनरेट किया गया कोड .. करने के लिए .. .. ..' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '। – Frank

उत्तर

7

मुझे यकीन नहीं है कि क्यों F # int64 श्रेणियों की अनुमति नहीं देता है। यह एक उपयोगी सुविधा की तरह लगता है ... (लेकिन मैं समझ सकता हूं कि int सी # में इसके लिए मानक प्रकार है और शायद F # इस पैटर्न का पालन करने का प्रयास करता है)।

let inline longFor low high f = 
    let rec loop n = 
    if n < high then f n; loop (n + 1L) 
    loop low 

... और फिर आप एक काफी संक्षिप्त रास्ते में int64 पर्वतमाला से अधिक for छोरों को व्यक्त कर सकते हैं:

समाधान के लिए, यह भी कहा कि आप भी लिख सकते हैं inline उच्च क्रम समारोह के लायक है:

longFor 1L 100L (fun n -> 
    <whatever>) 

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

केवल एक नुकसान है - आप स्थानीय परिवर्तनीय चर (let mutable) का उपयोग करने में सक्षम नहीं होंगे क्योंकि इन्हें लैम्ब्डा फ़ंक्शन द्वारा कैद नहीं किया जा सकता है। तो अप्रत्यक्ष ref कोशिकाओं के साथ अतिरिक्त लागत हो सकती है (लेकिन मुझे यकीन नहीं है कि यह कितनी बड़ी समस्या है)।

+1

+1 मैंने हाल ही में प्रयोग किया है कि कैसे एफ # कंपाइलर्स उच्च-आदेश कार्यों को रेखांकित करते हैं और मैं यह देखने के लिए आश्चर्यचकित हूं (और प्रसन्न) कि यह कम से कम F # 3.0 के रूप में कॉल साइट पर लैम्बडा को भी रेखांकित करता है। अब मैं आपके सुझाव के समान एक दृष्टिकोण का उपयोग करता हूं, लेकिन पूंछ-रिकर्सन के बजाए एक अनिवार्य जबकि लूप के साथ (इसलिए मैं एक रेफ सेल के बजाय सादे म्यूटेबल का उपयोग कर सकता हूं)। अब तक ठीक काम करने लगता है। – Frank

0

एक अन्य संभावित वैकल्पिक हल:

[1L..100L] |> सूची।आईटीईआर (मज़ा मैं -> printfn "% i" i)

2

आप के लिए लूप, वहाँ एक बहुत ही सरल for...in पाश के उपयोग के साथ है रखने के लिए एक sequence range operator साथ चाहते हैं:

for i in 0I .. 10I do 
    printfn "%A" i 

रेंज ऑपरेटर किसी भी आकार के किसी भी पूर्णांक को तब तक स्वीकार करेगा जब तक कि दोनों प्रकार के मिलान न हों। उदाहरण के लिए, निम्नलिखित होगा नहीं संकलन:

for i in 0 .. 10I do 
    printfn "%A" i 
+0

धन्यवाद, लेकिन मुझे इसके बारे में पता है; मेरे प्रश्न के दूसरे पैराग्राफ को पढ़ें। – Frank

+0

ओह ... याद आया। [एक और सवाल] से आ रहा था (http://stackoverflow.com/q/21292082/211627) ... – JDB

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