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

8
มีวิธีใดบ้างที่จะหลีกเลี่ยงการโอเวอร์โฟลว์สแต็กในอัลกอริทึมแบบเรียกซ้ำได้
คำถาม มีวิธีใดที่เป็นไปได้ในการแก้ปัญหาการล้นสแต็กที่เกิดจากอัลกอริทึมแบบเรียกซ้ำ ตัวอย่าง ฉันกำลังพยายามแก้ปัญหาProject Euler 14และตัดสินใจลองใช้อัลกอริทึมแบบเรียกซ้ำ อย่างไรก็ตามโปรแกรมหยุดทำงานด้วย java.lang.StackOverflowError เข้าใจได้. อัลกอริทึมโอเวอร์โฟลว์สแต็คจริง ๆ เพราะฉันพยายามสร้างลำดับ Collatz สำหรับจำนวนมาก โซลูชั่น ดังนั้นฉันจึงสงสัยว่า: วิธีการมาตรฐานแบบใดที่จะแก้ปัญหาสแต็คโอเวอร์โฟลว์โดยสมมติว่าอัลกอริธึมวนซ้ำของคุณเขียนอย่างถูกต้องและจะจบลงด้วยการล้นสแต็กเสมอ แนวคิดสองประการที่อยู่ในใจคือ: หางเรียกซ้ำ การย้ำ แนวคิด (1) และ (2) ถูกต้องหรือไม่ มีตัวเลือกอื่น ๆ อีกไหม? แก้ไข มันจะช่วยให้เห็นบางรหัสโดยเฉพาะอย่างยิ่งใน Java, C #, Groovy หรือ Scala อาจจะไม่ใช้ปัญหา Project Euler ที่กล่าวมาข้างต้นดังนั้นมันจะไม่ทำให้ผู้อื่นเสีย แต่ใช้อัลกอริทึมอื่น ๆ แฟกทอเรียลอาจหรือสิ่งที่คล้ายกัน

4
JVM มีข้อ จำกัด อะไรในการเพิ่มประสิทธิภาพการโทรแบบหาง
Clojure ไม่ได้ดำเนินการเพิ่มประสิทธิภาพการโทรหางในตัวเอง: recurเมื่อคุณมีหางฟังก์ชันเวียนและคุณต้องการที่จะมีมันที่ดีที่สุดที่คุณจะต้องใช้รูปแบบพิเศษ ในทำนองเดียวกันถ้าคุณมีสองฟังก์ชั่น recursive trampolineร่วมกันคุณสามารถเพิ่มประสิทธิภาพพวกเขาเท่านั้นโดยใช้ คอมไพเลอร์ Scala สามารถดำเนินการ TCO สำหรับฟังก์ชันแบบเรียกซ้ำ แต่ไม่ใช่สำหรับสองฟังก์ชันแบบเรียกซ้ำ เมื่อใดก็ตามที่ฉันได้อ่านเกี่ยวกับข้อ จำกัด เหล่านี้พวกเขามักจะกำหนดข้อ จำกัด ที่แท้จริงให้กับตัวแบบ JVM ฉันไม่รู้อะไรเลยเกี่ยวกับคอมไพเลอร์ แต่มันทำให้ฉันสับสนเล็กน้อย Programming Scalaผมขอใช้ตัวอย่างจาก ฟังก์ชั่นที่นี่ def approximate(guess: Double): Double = if (isGoodEnough(guess)) guess else approximate(improve(guess)) ถูกแปลเป็น 0: aload_0 1: astore_3 2: aload_0 3: dload_1 4: invokevirtual #24; //Method isGoodEnough:(D)Z 7: ifeq 10: …
36 scala  clojure  jvm  tail-call 

2
Y combinator และการปรับหางเรียกให้เหมาะสม
คำจำกัดความของ Y combinator ใน F # คือ let rec y f x = f (y f) x f คาดว่าจะเป็นอาร์กิวเมนต์แรกที่มีความต่อเนื่องสำหรับปัญหาย่อยแบบเรียกซ้ำ การใช้ yf เป็นสิ่งต่อเนื่องเราจะเห็นว่า f จะถูกนำไปใช้กับการโทรติดต่ออย่างต่อเนื่องในขณะที่เราสามารถพัฒนาได้ let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc... ปัญหาคือโครงร่างนี้ precludes โดยใช้การปรับ …

3
ทางเลือกใดในการใช้สแต็กเพื่อแสดงความหมายของการเรียกใช้ฟังก์ชัน?
เราทุกคนรู้และชื่นชอบที่การเรียกใช้ฟังก์ชันมักจะใช้งานโดยใช้ stack มีเฟรม, ที่อยู่ผู้ส่ง, พารามิเตอร์, ล็อตทั้งหมด อย่างไรก็ตามสแต็กเป็นรายละเอียดการใช้งาน: การเรียกประชุมอาจทำสิ่งต่าง ๆ (เช่น x86 fastcall ใช้ (ลงทะเบียน), MIPS และผู้ติดตามใช้หน้าต่างลงทะเบียนและอื่น ๆ ) และการเพิ่มประสิทธิภาพสามารถทำได้แม้กระทั่งสิ่งอื่น ๆ การเพิ่มประสิทธิภาพการโทรหาง .. ) แน่นอนว่าการมีคำสั่งกองซ้อนที่สะดวกในหลาย ๆ เครื่อง (VMs เช่น JVM และ CLR แต่ยังมีเครื่องจริงเช่น x86 ด้วย PUSH / POP เป็นต้น) ทำให้สะดวกในการใช้งานสำหรับการเรียกใช้ฟังก์ชั่น แต่ในบางกรณีก็เป็นไปได้ เพื่อตั้งโปรแกรมในลักษณะที่ไม่จำเป็นต้องใช้ call stack (ฉันกำลังคิดเกี่ยวกับสไตล์การส่งผ่านต่อเนื่องที่นี่หรือนักแสดงในระบบส่งข้อความ) ดังนั้นฉันเริ่มสงสัยว่า: เป็นไปได้หรือไม่ที่จะใช้ semantics call function โดยไม่มี …

4
เมื่อไม่มี TCO เมื่อใดต้องกังวลเกี่ยวกับการสแต็คกอง?
ทุกครั้งที่มีการอภิปรายเกี่ยวกับภาษาการเขียนโปรแกรมใหม่ที่กำหนดเป้าหมาย JVM ย่อมมีคนพูดถึงสิ่งต่าง ๆ เช่น: "JVM ไม่รองรับการปรับให้เหมาะสมแบบหางเรียกดังนั้นฉันทำนายสแต็กการระเบิดจำนวนมาก" ชุดรูปแบบนั้นมีการเปลี่ยนแปลงหลายพันรายการ ตอนนี้ฉันรู้ว่าบางภาษาเช่น Clojure มีโครงสร้างการเกิดขึ้นเป็นพิเศษที่คุณสามารถใช้ สิ่งที่ฉันไม่เข้าใจคือ: การขาดการเพิ่มประสิทธิภาพการโทรหางมีความร้ายแรงเพียงใด? ฉันควรกังวลเกี่ยวกับเรื่องนี้เมื่อใด แหล่งที่มาหลักของความสับสนอาจมาจากความจริงที่ว่า Java เป็นหนึ่งในภาษาที่ประสบความสำเร็จมากที่สุดและภาษา JVM บางส่วนดูเหมือนจะทำได้ค่อนข้างดี วิธีการที่เป็นไปได้ถ้าขาดการ TCO เป็นจริงของใด ๆกังวล?
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.