คำถามติดแท็ก tail-recursion

การเรียกซ้ำหางเป็นกลยุทธ์การเรียกซ้ำซึ่งฟังก์ชันทำงานบางส่วนแล้วเรียกใช้ตัวเอง "หาง" หมายถึงความจริงที่ว่าการเรียกซ้ำอยู่ที่ส่วนท้ายสุดของฟังก์ชัน คอมไพเลอร์ภาษาการเขียนโปรแกรมหลายตัวโดยเฉพาะที่ใช้งานได้สามารถเปลี่ยนการเรียกประเภทนี้ให้เป็นการวนซ้ำได้ซึ่งหมายความว่าการเรียกซ้ำหางในภาษาที่รองรับสามารถใช้ได้โดยไม่ต้องกลัวว่าจะมีสแต็กล้นโดยไม่คำนึงถึงจำนวนครั้ง


10
การเพิ่มประสิทธิภาพการโทรหางคืออะไร?
ง่ายมากการเพิ่มประสิทธิภาพการโทรแบบหางคืออะไร โดยเฉพาะอย่างยิ่งมีโค้ดขนาดเล็กอะไรบ้างที่สามารถนำไปใช้และไม่ได้มีคำอธิบายว่าทำไม

19
ฉันจะแยกวงใน Scala ได้อย่างไร
ฉันจะแยกวงได้อย่างไร var largest=0 for(i<-999 to 1 by -1) { for (j<-i to 1 by -1) { val product=i*j if (largest>product) // I want to break out here else if(product.toString.equals(product.toString.reverse)) largest=largest max product } } ฉันจะเปลี่ยนลูปเป็นลูปเป็นการวนรอบแบบวนซ้ำได้อย่างไร? จาก Scala Talk ที่ FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261 ในหน้า 22: ทำลายและดำเนินการต่อสกาล่าไม่ได้มีพวกเขา ทำไม? พวกเขามีความจำเป็นเล็กน้อย ดีกว่าใช้ฟังก์ชั่นขนาดเล็กจำนวนมากออกวิธีการโต้ตอบกับการปิด พวกเขาไม่ต้องการ! คำอธิบายคืออะไร

20
ทำความเข้าใจกับการเรียกซ้ำ [ปิด]
ตามที่เป็นอยู่ในปัจจุบันคำถามนี้ไม่เหมาะสำหรับรูปแบบคำถาม & คำตอบของเรา เราคาดหวังคำตอบที่จะได้รับการสนับสนุนจากข้อเท็จจริงการอ้างอิงหรือความเชี่ยวชาญ แต่คำถามนี้มีแนวโน้มที่จะเรียกร้องการอภิปรายการโต้แย้งการหยั่งเสียงหรือการอภิปรายเพิ่มเติม หากคุณรู้สึกว่าคำถามนี้สามารถปรับปรุงและเปิดใหม่ได้โปรดไปที่ศูนย์ช่วยเหลือเพื่อขอคำแนะนำ ปิดให้บริการใน7 ปีที่ผ่านมา ฉันมีปัญหาใหญ่ในการทำความเข้าใจเรื่องการเรียกซ้ำที่โรงเรียน เมื่อไรก็ตามที่อาจารย์พูดถึงมันฉันก็ดูเหมือนจะเข้าใจ แต่เมื่อฉันลองด้วยตัวเองมันจะทำให้สมองของฉันพังทลาย ฉันพยายามที่จะไขหอคอยแห่งฮานอยตลอดทั้งคืนและทำให้ใจฉันสนิท หนังสือเรียนของฉันมีการเรียกซ้ำประมาณ 30 หน้าเท่านั้นดังนั้นจึงไม่มีประโยชน์ ไม่มีใครรู้หนังสือหรือแหล่งข้อมูลที่สามารถช่วยชี้แจงหัวข้อนี้ได้บ้าง?

6
Python ปรับหางแบบวนซ้ำให้เหมาะสมหรือไม่?
ฉันมีรหัสต่อไปนี้ซึ่งล้มเหลวด้วยข้อผิดพลาดต่อไปนี้: RuntimeError: เกินความลึกการเรียกซ้ำสูงสุด ฉันพยายามเขียนสิ่งนี้เพื่ออนุญาตการปรับให้เหมาะสมแบบเรียกซ้ำหาง (TCO) ฉันเชื่อว่ารหัสนี้ควรจะประสบความสำเร็จหาก TCO เกิดขึ้น def trisum(n, csum): if n == 0: return csum else: return trisum(n - 1, csum + n) print(trisum(1000, 0)) ฉันควรสรุปได้หรือไม่ว่า Python ไม่ได้ทำ TCO ประเภทใดหรือฉันต้องกำหนดมันให้แตกต่างกันหรือไม่?

5
คอมไพเลอร์ C ++ ใดที่มีการปรับให้เหมาะสมแบบเรียกซ้ำ
ดูเหมือนว่าสำหรับฉันแล้วมันจะทำงานได้อย่างสมบูรณ์แบบดีในการปรับการเรียกซ้ำแบบหางทั้งใน C และ C ++ แต่ในขณะที่การดีบั๊กฉันไม่เคยเห็นเฟรมสแต็คที่ระบุการเพิ่มประสิทธิภาพนี้ นั่นเป็นสิ่งที่ดีเพราะกองซ้อนบอกฉันว่าการเรียกซ้ำนั้นลึกซึ้งเพียงใด อย่างไรก็ตามการเพิ่มประสิทธิภาพจะเป็นสิ่งที่ดีเช่นกัน คอมไพเลอร์ C ++ มีการเพิ่มประสิทธิภาพนี้หรือไม่? ทำไม? ทำไมจะไม่ล่ะ? ฉันจะบอกให้คอมไพเลอร์ทำอย่างไร สำหรับ MSVC: /O2หรือ/Ox สำหรับ GCC: -O2หรือ-O3 วิธีการตรวจสอบว่าคอมไพเลอร์ได้ทำในกรณีที่แน่นอนหรือไม่ สำหรับ MSVC ให้เปิดใช้งานเอาต์พุต PDB เพื่อให้สามารถติดตามรหัสจากนั้นตรวจสอบรหัส สำหรับ GCC .. ฉันยังคงแนะนำวิธีการตรวจสอบว่าฟังก์ชั่นบางอย่างได้รับการปรับให้เหมาะสมเช่นนี้โดยคอมไพเลอร์ (แม้ว่าฉันจะพบว่ามันมั่นใจว่า Konrad บอกให้ฉันสมมติมัน) มันเป็นไปได้เสมอที่จะตรวจสอบว่าคอมไพเลอร์ทำสิ่งนี้ด้วยการเรียกซ้ำแบบไม่สิ้นสุดและตรวจสอบว่ามันส่งผลให้เกิดการวนซ้ำไม่สิ้นสุดหรือสแต็กล้น (ฉันทำสิ่งนี้กับ GCC และพบว่า-O2เพียงพอ) แต่ฉันต้องการ สามารถตรวจสอบฟังก์ชั่นบางอย่างที่ฉันรู้ว่าจะยุติได้ ฉันชอบที่จะมีวิธีง่ายๆในการตรวจสอบเรื่องนี้ :) หลังจากการทดสอบบางอย่างฉันพบว่า destructors ทำลายความเป็นไปได้ของการเพิ่มประสิทธิภาพนี้ บางครั้งมันก็คุ้มค่าที่จะเปลี่ยนการกำหนดขอบเขตของตัวแปรและเทมเพลตบางอย่างเพื่อให้แน่ใจว่าพวกเขาออกนอกขอบเขตก่อนที่แถลงผลตอบแทนจะเริ่มต้น หาก destructor ใด ๆ …

8
การเรียกซ้ำหางทำงานอย่างไร?
ฉันเกือบจะเข้าใจว่าการเรียกซ้ำหางทำงานอย่างไรและความแตกต่างระหว่างการเรียกซ้ำแบบปกติ ฉันเพียง แต่ไม่เข้าใจว่าทำไมมันไม่จำเป็นต้องมีสแต็คที่ต้องจำอยู่กลับ // tail recursion int fac_times (int n, int acc) { if (n == 0) return acc; else return fac_times(n - 1, acc * n); } int factorial (int n) { return fac_times (n, 1); } // normal recursion int factorial (int n) { if (n == 0) …

6
เหตุใด. NET / C # จึงไม่ปรับให้เหมาะสมสำหรับการเรียกซ้ำหางโทร
ฉันพบคำถามนี้เกี่ยวกับภาษาที่เพิ่มประสิทธิภาพการเรียกซ้ำหาง เหตุใด C # จึงไม่เพิ่มประสิทธิภาพการเรียกซ้ำหางเมื่อใดก็ตามที่ทำได้ สำหรับกรณีที่เป็นรูปธรรมเหตุใดจึงไม่ปรับวิธีนี้ให้เหมาะสมกับการวนซ้ำ ( Visual Studio 2008 32 บิตถ้าเป็นเช่นนั้น): private static void Foo(int i) { if (i == 1000000) return; if (i % 100 == 0) Console.WriteLine(i); Foo(i+1); }

5
JVM ป้องกันการเพิ่มประสิทธิภาพการโทรหางหรือไม่
ฉันเห็นคำพูดนี้ในคำถาม: ภาษาที่ใช้งานได้ดีในการสร้างบริการเว็บคืออะไร? โดยเฉพาะอย่างยิ่ง Scala ไม่รองรับการกำจัดหางโทรยกเว้นในฟังก์ชันเรียกซ้ำในตัวเองซึ่ง จำกัด ประเภทขององค์ประกอบที่คุณสามารถทำได้ (นี่เป็นข้อ จำกัด พื้นฐานของ JVM) นี่คือเรื่องจริง? ถ้าเป็นเช่นนั้น JVM ที่สร้างข้อ จำกัด พื้นฐานนี้คืออะไร?

5
Ruby ทำการเพิ่มประสิทธิภาพการโทรหางหรือไม่
ภาษาที่ใช้งานได้นำไปสู่การใช้การเรียกซ้ำเพื่อแก้ปัญหาจำนวนมากดังนั้นหลายภาษาจึงใช้ Tail Call Optimization (TCO) TCO ทำให้เกิดการเรียกใช้ฟังก์ชันจากฟังก์ชันอื่น (หรือตัวเองซึ่งในกรณีนี้คุณลักษณะนี้เรียกอีกอย่างว่า Tail Recursion Elimination ซึ่งเป็นส่วนย่อยของ TCO) เป็นขั้นตอนสุดท้ายของฟังก์ชันนั้นโดยไม่ต้องใช้สแต็กเฟรมใหม่ ซึ่งลดค่าใช้จ่ายและการใช้หน่วยความจำ เห็นได้ชัดว่า Ruby ได้ "ยืม" แนวคิดหลายอย่างจากภาษาที่ใช้งานได้ (lambdas, ฟังก์ชันเช่น map เป็นต้น) ซึ่งทำให้ฉันสงสัยว่า Ruby ทำการเพิ่มประสิทธิภาพการโทรหางหรือไม่?

6
JavaScript Engine tail call (TCO) ได้รับการปรับให้เหมาะสมหรือไม่
ฉันมีอัลกอริธึมการค้นหาพา ธ แบบเรียกซ้ำหางที่ฉันติดตั้งใน JavaScript และต้องการทราบว่าเบราว์เซอร์ใด ๆ (ทั้งหมด?) อาจได้รับข้อยกเว้นสแต็กโอเวอร์

4
Haskell มีการเพิ่มประสิทธิภาพหางซ้ำหรือไม่?
วันนี้ฉันค้นพบคำสั่ง "time" ใน unix และคิดว่าจะใช้เพื่อตรวจสอบความแตกต่างของเวลาทำงานระหว่างฟังก์ชันการเรียกซ้ำแบบหางซ้ำและฟังก์ชันเรียกซ้ำแบบปกติใน Haskell ฉันเขียนฟังก์ชันต่อไปนี้: --tail recursive fac :: (Integral a) => a -> a fac x = fac' x 1 where fac' 1 y = y fac' x y = fac' (x-1) (x*y) --normal recursive facSlow :: (Integral a) => a -> a facSlow 1 = 1 …

1
จะให้เหตุผลเกี่ยวกับความปลอดภัยของกองซ้อนใน Scala Cats / fs2 ได้อย่างไร
นี่คือชิ้นส่วนของรหัสจากเอกสารสำหรับFS2 ฟังก์ชั่นgoซ้ำ คำถามคือเราจะรู้ได้อย่างไรว่าปลอดภัยสำหรับสแต็กและวิธีการใช้ฟังก์ชันใดที่ปลอดภัยสแต็ก import fs2._ // import fs2._ def tk[F[_],O](n: Long): Pipe[F,O,O] = { def go(s: Stream[F,O], n: Long): Pull[F,O,Unit] = { s.pull.uncons.flatMap { case Some((hd,tl)) => hd.size match { case m if m <= n => Pull.output(hd) >> go(tl, n - m) case m => Pull.output(hd.take(n.toInt)) >> Pull.done } …
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.