2009-11-04 20 views

उत्तर

62

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

निम्नलिखित स्निपेट का प्रयास करें:

def boom(n: Int): Nothing = if(n<=0) throw new Exception else boom(n-1) 
boom(10) 

और स्टैक ट्रेस का निरीक्षण किया। यह फ़ंक्शन बूम पर केवल एक कॉल दिखाएगा - इसलिए संकलित बाइटकोड रिकर्सिव नहीं है।

implement tail calls at the JVM level पर चारों ओर तैरने वाला एक प्रस्ताव है - जो मेरी राय में करने के लिए एक बड़ी बात होगी, तब JVM कोड के समय अनुकूलन को संकलित करने के बजाय रनटाइम अनुकूलन कर सकता है - और संभवतः अधिक लचीला पूंछ हो सकता है प्रत्यावर्तन। मूल रूप से एक tailcall invoke एक सामान्य विधि invoke की तरह वास्तव में व्यवहार करते हैं, लेकिन फोन करने वाले के ढेर छोड़ देंगे जब यह ऐसा करने के लिए सुरक्षित है - JVM कहा गया है कि फ्रेम ढेर संरक्षित किया जाना चाहिए के विनिर्देश, तो JIT करने के लिए कुछ स्थिर कोड विश्लेषण करना है पता लगाएं कि स्टैक फ्रेम का उपयोग कभी नहीं किया जा रहा है।

यह की वर्तमान स्थिति proto 80% है। मुझे नहीं लगता कि यह जावा 7 के लिए समय पर किया जाएगा (invokedynamic की प्राथमिकता है, और कार्यान्वयन लगभग पूरा हो गया है) लेकिन जावा 8 इसे लागू कर सकता है।

+0

"यह की वर्तमान स्थिति आद्य है 80% "। मुझे समझ में नहीं आता मैंने सोचा था कि अर्नोल्ड श्वाइघोफर ने साल पहले जॉन रोज के मार्गदर्शन के तहत इसे पूरी तरह कार्यान्वित किया था? –

+0

@ जेनहार्प शायद सामान्य पूंछ कॉल की बजाय पूंछ रिकर्सन के बारे में था? – Cubic

+0

@ क्यूबिक: नहीं, यह सामान्य पूंछ कॉल था। अर्नोल्ड ने उन्हें एलएलवीएम में भी लागू किया। –

7

केवल बहुत ही सरल मामलों में जहां कार्य स्वयं-पुनरावर्ती है।

Proof of tail recursion ability.

यह स्काला 2.8 की तरह लग रहा पूंछ-प्रत्यावर्तन मान्यता में सुधार है, हालांकि हो सकता है।

+1

"केवल बहुत ही सरल मामलों में जहां कार्य स्वयं-पुनरावर्ती है।": क्या इसका मतलब यह है कि निरंतरता का उपयोग करते समय कोई आसानी से स्टैक स्पेस से बाहर हो सकता है? – Giorgio

+0

@Giorgio: हाँ .. –

12

स्काला 2.7.x अंतिम तरीकों और स्थानीय कार्यों के आत्म-प्रत्यावर्तन के लिए पूंछ-कॉल अनुकूलन (एक समारोह में ही बुला) का समर्थन करता है।

स्काला 2.8 जो पारस्परिक रूप से पुनरावर्ती कार्यों का अनुकूलन करने के लिए एक तकनीक है भी ट्रैम्पोलिन के पुस्तकालय समर्थन, लग सकता है।

एक स्काला प्रत्यावर्तन की स्थिति की जानकारी के अच्छा सौदा Rich Dougherty's blog में पाया जा सकता।

+1

इसके अलावा के बारे में monadic ट्रैम्पोलाइंस: http://apocalisp.wordpress.com/2011/10/26/tail-call-elimination-in-scala-monads/ – Vadzim

41

स्काला 2.8 में आप विशिष्ट विधि है कि आप आशा है कि संकलक अनुकूलित करेंगे चिह्नित करने के लिए @tailrec उपयोग कर सकते हैं:

import scala.annotation.tailrec 

@tailrec def factorialAcc(acc: Int, n: Int): Int = { 
    if (n <= 1) acc 
    else factorialAcc(n * acc, n - 1) 
} 

एक विधि अनुकूलित नहीं किया जा सकता है, तो आपको यह चेतावनी मिलती।

+13

"आयात scala.annotation.tailrec" के साथ एनोटेशन आयात करना आवश्यक है – Callum

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