JavaScript Engine tail call (TCO) ได้รับการปรับให้เหมาะสมหรือไม่


91

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


2
มันเป็นอัลกอริธึมแบบวนซ้ำหรืออัลกอริทึมซ้ำที่ใช้กับการเรียกซ้ำ? ความเข้าใจของฉันคือ TCO สามารถช่วยได้ในช่วงหลังเท่านั้น
nmichaels

1
ฉันแค่อยากจะเพิ่มว่า TCO ไม่ใช่onlyการเพิ่มประสิทธิภาพ การสนับสนุนควรเป็นส่วนหนึ่งของข้อกำหนดภาษาไม่ใช่คอมไพเลอร์ / ล่ามเนื่องจากโค้ดที่เขียนเทียบกับล่าม / คอมไพเลอร์หนึ่งตัวที่มี TCO อาจใช้ไม่ได้กับล่าม / คอมไพเลอร์ที่ไม่มี TCO
Hoffmann

1
คุณสามารถดูการสนับสนุนในปัจจุบันและดูการพัฒนาของเครื่องยนต์ในตารางความเข้ากันได้กับ ES6 ของ Kangax ได้ที่นี่: kangax.github.io/compat-table/es6/…
Roy Tinker

คำตอบ:


47

ข้อกำหนด ECMAScript 4 เดิมจะเพิ่มการสนับสนุนสำหรับ TCO แต่ถูกยกเลิก:

ไม่มีการเรียกหางใน JavaScript อีกต่อไป?

เท่าที่ฉันทราบไม่มีการใช้งาน JavaScript ที่แพร่หลายในปัจจุบันทำให้ TCO อัตโนมัติ สิ่งนี้อาจเป็นประโยชน์สำหรับคุณแม้ว่า:

การเพิ่มประสิทธิภาพการโทรหาง

โดยพื้นฐานแล้วการใช้รูปแบบตัวสะสมจะได้ผลเช่นเดียวกัน


1
เพียงแค่ FYI Rhino มี TCO อัตโนมัติพร้อมกับความต่อเนื่องในโหมด "ตีความ" (opt = -1) wiki.apache.org/cocoon/RhinoWithContinuation
Mark Porter

5
(ขออภัยที่หลอก) ECMAScript 6 ได้รวม TCO ซึ่งเรียกว่าการโทรหางที่เหมาะสมในข้อกำหนด
หนาวจัด

@sclv: อะไรคือการอ้างอิงแทรมโพลีน?
bukzor

39
รูปแบบตัวสะสมไม่บรรลุผลเช่นเดียวกับ TCO มันเป็นเพียงการแปลงอัลกอริทึมแบบวนซ้ำเป็นรูปแบบหางซ้ำ นี่เป็นข้อกำหนดเบื้องต้นเพื่อให้ TCO เป็นไปได้ แต่ไม่สามารถทดแทนได้ คุณจะยังคงระเบิดสแต็กในภาษาที่ไม่ได้ปรับการโทรหาง
Marcelo Cantos

"ไม่มีการใช้งาน JS ที่ใช้งานได้ทั่วไปในปัจจุบันทำให้ TCO อัตโนมัติ" สิ่งนี้ไม่ถูกต้องสำหรับโหนด 6.2.0 หากคุณส่งค่าสถานะที่ถูกต้อง
Janus Troelsen

26

ไม่มีความสุขในขณะนี้ แต่โชคดีที่การเรียกหางที่เหมาะสมถูกกำหนดไว้สำหรับ Harmony (ECMAScript เวอร์ชัน 6) http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur คำถามเกี่ยวกับเบราว์เซอร์โดยเฉพาะไม่ใช่การใช้ ECMAScript ที่มีอยู่ทั้งหมด
รหัสไร้ประโยชน์

1
@UselessCode Nope คำถามนี้เกี่ยวกับ "Javascript engine" ดังนั้น ... ไม่ใช่แค่เบราว์เซอร์
BT

1
@BT มีสภาพแวดล้อม JS ที่ไม่ใช่เบราว์เซอร์จำนวนมากและชื่อเรื่องใช้ "Javascript engine" ทั่วไปมากกว่า แต่เนื้อหาของคำถามระบุว่า "... ต้องการทราบว่าเบราว์เซอร์ (ทั้งหมด?) อาจได้รับสแต็ก ข้อยกเว้นล้น "
รหัสไร้ประโยชน์

ต้องโต้ "แต่ชื่อเรื่องว่า ... ". ฉันคิดว่าเพราะเขาพูดถึงทั้งสองคำถามจึงเกี่ยวกับทั้งสองอย่าง แต่คุณพูดถูกถ้าคุณบอกว่ามันไม่ได้ทำให้คำตอบล้าสมัย
BT

4
@MarkWilbur เท่าที่ฉันทราบโหนดที่ใช้ v8 เวอร์ชันเดียวกับโครเมี่ยมซึ่งปัจจุบันไม่รองรับ TCO ฉันมีส่วนสำคัญกับ JS และแอสเซมเบลอร์ที่ปรับให้เหมาะสมที่ V8 ปัจจุบันสร้างขึ้น - gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr

12

เกือบทุกเบราว์เซอร์ที่คุณพบจะ จำกัด อยู่ที่ "การเรียกซ้ำมากเกินไป" นี่คือรายการในตัวติดตามข้อผิดพลาด V8ที่น่าจะอ่านได้

หากเป็นการเรียกซ้ำด้วยตัวเองง่ายๆก็น่าจะคุ้มค่ากับความพยายามที่จะใช้การวนซ้ำอย่างชัดเจนแทนที่จะหวังว่าจะกำจัดการโทรออก


ข้อบกพร่องได้รับการยอมรับในที่สุด มันอยู่ภายใต้มหากาพย์: "Feature Request Harmony" หวังว่านั่นหมายความว่าพวกเขาวางแผนที่จะเพิ่มการสนับสนุน ES6 ใน V8
Txangel

คุณสามารถลงคะแนนสำหรับการสนับสนุน TCO ใน Internet Explorer ได้ที่นี่: wpdev.uservoice.com/forums/257854-internet-explorer-platform/…
Roy Tinker

12

การเพิ่มประสิทธิภาพการโทรหางจะได้รับการสนับสนุนในโหมดเข้มงวด ECMAScript 6 ในอนาคต ตรวจสอบhttp://www.2ality.com/2015/06/tail-call-optimization.htmlสำหรับรายละเอียด

ตรวจสอบhttp://kangax.github.io/compat-table/es6/สำหรับการสนับสนุนเครื่องยนต์ปัจจุบัน

ในขณะนี้ (18-07-2019) เครื่องยนต์ต่อไปนี้รองรับการเพิ่มประสิทธิภาพการโทรหาง:

  • Safari> = 10
  • iOS> = 10
  • Kinoma XS6
  • Duktape 2.3

สนับสนุนหาก "คุณลักษณะ JavaScript ทดลอง" เปิดอยู่:

  • โหนด 6.5
  • Chrome 54 / Opera 41เวอร์ชันปัจจุบันของตารางที่เข้ากันได้ไม่แสดงรายการอีกต่อไป

3

ขณะนี้การเพิ่มประสิทธิภาพการโทรหางพร้อมใช้งานแล้วในLispyScriptซึ่งคอมไพล์เป็น JavaScript คุณสามารถอ่านเพิ่มเติมได้ที่นี่


แล้วการเรียกซ้ำร่วมกันล่ะ?
แมว

2

ขณะนี้ไม่มีการใช้งาน JavaScript ที่รู้จักการเรียกซ้ำหาง การเปลี่ยนแปลงจะถูกทำในECMAScript 6และเป็นคนอื่น ๆ ได้กล่าวว่ามีตั๋วที่เปิดในV8

ที่นี่คุณสามารถดูแอสเซมเบลอร์ที่สร้างขึ้นของ V8 สำหรับฟังก์ชันการเรียกซ้ำหาง:

ตัวอย่างวิธีที่ V8 รวบรวมการเรียกซ้ำ

เปรียบเทียบกับวิธีที่Clangรวบรวมฟังก์ชันเดียวกันใน C

ตัวอย่างการเรียกซ้ำของ C compiler tail

V8 จะเก็บการเรียกแบบเรียกซ้ำในขณะที่คอมไพเลอร์ C จดจำการเรียกซ้ำของหางและเปลี่ยนเป็นลูป


"ขณะนี้ไม่มีการใช้งาน JS ที่จดจำการเรียกซ้ำหาง" ที่ไม่ถูกต้องสำหรับโหนด 6.2.0 แต่คุณต้องส่งธง
Janus Troelsen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.