2013-08-27 15 views
5

मैं इस कोड है। कोई विचार क्यों पूंछ रिकर्सन का उपयोग करने के लिए संकलित नहीं किया गया है?एफ # पूंछ पुनरावर्ती कॉल

+2

आप कर रहे हैं:

public static FSharpSet<int> collect(FSharpList<int> t, FSharpSet<int> acc) { while (true) { FSharpList<int> fSharpList = t; if (fSharpList.TailOrNull == null) break; // The following corresponds to the second case FSharpList<int> tl = fSharpList.TailOrNull; int hr = fSharpList.HeadOrDefault; // Variables 'acc' and 't' are mutated (instead of calling the function) acc = SetModule.Union<int>(acc, Program.FindSourceFilesForTarget<int>(hr)); t = tl; } return acc; } 

एक से थोड़ा असंबंधित नोट पर, आप भी इस का उपयोग कर मानक पुस्तकालय कार्यों व्यक्त कर सकते हैं: यह (जब आप परावर्तक का उपयोग सी # करने के लिए इसे चालू करने के) कैसे संकलित कोड लग रहा है रिलीज मोड में संकलन? जब तक आप रिहाई मोड में न हों तब तक टेल कॉल को अनुकूलित नहीं किया जाता है। – mydogisbox

उत्तर

10

जहाँ तक मैं कह सकता हूं, collect फ़ंक्शन वास्तव में पूंछ-पुनरावर्ती है। पहला मामला स्पष्ट रूप से acc देता है। दूसरा मामला पहले FindSourceFilesForTarget को आमंत्रित करता है, फिर Set.union पर कॉल करता है और फिर लौटाता है। आप इसे फिर से लिखने सकता है इस प्रकार है (जो अधिक स्पष्ट रूप से पूंछ-प्रत्यावर्तन से पता चलता):

| hr::tl -> 
    let sources = FindSourceFilesForTarget hr 
    let acc = Set.union acc sources 
    collect tl 

क्योंकि यह सिर्फ एक समारोह में ही बुला, संकलक एक पाश में अनुकूलित करता है।

t |> Seq.map FindSourceFilesForTarget |> Set.unionMany 
+0

उत्तर के लिए धन्यवाद। साइड प्रश्न के रूप में, यदि यूनियन मैनी का उपयोग करते हैं, तो पाइपलाइन जैसे ही यह उपलब्ध हो जाता है विलय सेट शुरू हो जाता है या जब तक यह पिछले पाइपलाइन चरण ("Seq.map FindSourceFilesForTarget" से सभी आउटपुट एकत्र करता है तब तक प्रतीक्षा करता है)? कारण मैं रिकर्सिव कॉल कर रहा था क्योंकि सेट पर यूनियन करना है क्योंकि वे बहुत सारे डेटा हैं और वहां बहुत सारे डेटा हैं (100 हजारों), इसलिए मैं सभी परिणामों को कैश नहीं करना चाहता था और चाहता था जितनी जल्दी हो सके डुप्लिकेट को हटा दें – phwp

+0

जब 't' एक आलसी डेटा स्रोत (' IENumerable') है तो 'UnionMany' ऑपरेशन को मांग पर पढ़ना चाहिए (और इसलिए 'FindSourceFilesForTarget' भी मांग पर मूल्यांकन किया जाएगा)। तो मुझे लगता है कि इस मामले में, संपूर्ण डेटा सेट को रास्ते में स्मृति में लोड नहीं किया जाएगा। –

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