2011-03-17 18 views
7

जांच इस स्काला कोड:यह पूंछ रिकर्सिव क्यों है?

def rec(n: Int) { 
    if (n > 1) { 
    val d = n/2 
    rec(d) 
// if (d > 1) // abort loop 
     rec(n/d) 
    } 
} 

इस कोड को एक अंतहीन लूप में परिणाम होगा। पूंछ रिकर्सिव ऑप्टिमाइज़ेशन के कारण मुझे स्टैक ओवरफ्लो एरर नहीं मिलता है।

jad साथ decompiled मैं इस जावा कोड मिला:

public void rec(int n) 
{ 
    int d; 
    for(; n > 1; n /= d) 
    { 
     int i = n; 
     d = i/2; 
     rec(d); 
    } 
} 

पाश विधि ही कहता है इसलिए मैं पूंछ कॉल स्थिति समझ में नहीं आता की अंतिम पंक्ति में। कोई भी जो इसे समझा सकता है?

+0

यह सहायक होगा 1.http: //www.cs.wayne.edu/~artem/main/teaching/csc3200ss2006/slides/recursion/types.html 2.http: //stackoverflow.com/questions/ 105,834/करता है-JVM-रोकने पूंछ-कॉल-अनुकूलन –

उत्तर

9

rec(d) के मामले में कोई पूंछ कॉल नहीं है। rec(N) के लिए (जहां N > 1) log2(N) कॉल के बाद स्टैक अब और नहीं बढ़ता है (क्योंकि n के बाद 2 या 3 के बराबर है, और d 1 है)। उसके बाद यह आंतरिक rec(1) कॉल के साथ केवल अनंत लूप है जो तुरंत हर बार लौटाता है। यही कारण है कि ढेर अतिप्रवाह नहीं है।

3

आपकी विधि के पुनरावर्ती रूप में आपके पास दो रिकर्सिव कॉल हैं। StackOverflowError उनमें से अंतिम के कारण होता है।

पूंछ रिकर्सन ऑप्टिमाइज़ेशन के कारण, अंतिम कॉल लूप में बदल जाता है (जबकि पहली कॉल रिकर्सिव रखी जाती है), इसलिए आपके पास अनंत रिकर्सन के बजाय अनंत लूप है, और StackOverflowError ऐसा नहीं होता है।

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