Có bất kỳ lệnh gọi đuôi (TCO) nào của công cụ JavaScript được tối ưu hóa không?


91

Tôi có một thuật toán tìm đường đệ quy đuôi mà tôi đã triển khai trong JavaScript và muốn biết liệu có bất kỳ (tất cả?) Trình duyệt nào có thể nhận được ngoại lệ tràn ngăn xếp hay không.


2
Nó thực sự là một thuật toán đệ quy, hay một thuật toán lặp được thực hiện với đệ quy? Sự hiểu biết của tôi là TCO chỉ có thể giúp đỡ phần sau.
nmichaels,

1
Tôi chỉ muốn nói thêm rằng TCO không phải onlylà một tối ưu hóa. Hỗ trợ nó phải là một phần của đặc tả ngôn ngữ, không phải trình biên dịch / trình thông dịch vì mã được viết dựa trên một trình thông dịch / trình biên dịch với TCO có thể sẽ không hoạt động trên trình thông dịch / trình biên dịch mà không có TCO.
Hoffmann

1
Bạn có thể xem hỗ trợ hiện tại và xem nó phát triển trên các động cơ trong bảng tương thích ES6 của Kangax tại đây: kangax.github.io/compat-table/es6/…
Roy Tinker

Câu trả lời:


47

Đặc tả ECMAScript 4 ban đầu sẽ thêm hỗ trợ cho TCO, nhưng nó đã bị loại bỏ:

Không có lệnh gọi đuôi nào nữa trong JavaScript?

Theo như tôi biết, hiện tại không có triển khai JavaScript phổ biến nào thực hiện TCO tự động. Tuy nhiên, điều này có thể hữu ích cho bạn:

Tối ưu hóa cuộc gọi đuôi

Về cơ bản, việc sử dụng mẫu tích lũy sẽ mang lại hiệu quả tương tự.


1
Chỉ cần một FYI, Rhino có tự động TCO cùng với sự tiếp tục trong "giải thích" chế độ (opt = -1) wiki.apache.org/cocoon/RhinoWithContinuations
Mark Porter

5
(xin lỗi vì đã nói xấu) ECMAScript 6 đã bao gồm TCO, được gọi là Lệnh gọi đuôi thích hợp trong đặc điểm kỹ thuật.
băng giá

@sclv: Tham khảo tấm bạt lò xo là gì?
bukzor

39
Mẫu tích lũy không đạt được hiệu quả tương tự như TCO. Nó chỉ đơn thuần là biến đổi các thuật toán đệ quy thành dạng đệ quy đuôi. Đây là điều kiện tiên quyết để TCO có thể thực hiện được, nhưng nó không thể thay thế được. Bạn vẫn sẽ làm nổ tung ngăn xếp bằng ngôn ngữ không tối ưu hóa các cuộc gọi đuôi.
Marcelo Cantos

"triển khai rộng rãi không-có sẵn của JS hiện đang làm tự động TCO" này là không chính xác như các Node 6.2.0, nếu bạn vượt qua cờ đúng
Janus Troelsen

26

Không vui trong lúc này, nhưng may mắn thay, các cuộc gọi đuôi thích hợp được dự kiến ​​cho Harmony (ECMAScript phiên bản 6) http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur Câu hỏi đặc biệt là về các trình duyệt , không phải tất cả các triển khai hiện có của ECMAScript.
Mã vô dụng

1
@UselessCode Không, câu hỏi này là về "công cụ Javascript", vì vậy ... không chỉ trình duyệt
BT

1
@BT Thực sự có nhiều môi trường JS không phải là trình duyệt và tiêu đề sử dụng các "công cụ Javascript" chung chung hơn nhưng phần nội dung câu hỏi chỉ định "... muốn biết liệu có bất kỳ (tất cả?) Trình duyệt nào có thể nhận được ngăn xếp không ngoại lệ tràn. "
Mã vô dụng,

Tôi phải phản bác "nhưng tiêu đề nói rằng ...". Tôi nghĩ vì anh ấy đề cập đến cả hai, câu hỏi là về cả hai. Nhưng bạn đúng nếu bạn nói nó không làm cho câu trả lời trở nên lỗi thời.
BT

4
@MarkWilbur Theo như tôi biết nút sử dụng cùng phiên bản v8 với chrome - hiện không hỗ trợ TCO Tôi đã có ý kiến ​​với JS và trình hợp dịch được tối ưu hóa mà V8 hiện tại tạo ra - gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr

12

Khá nhiều trình duyệt bạn gặp phải sẽ gặp phải "quá nhiều đệ quy". Đây là một mục trong trình theo dõi lỗi V8 có thể sẽ rất thú vị khi đọc.

Nếu đó là phép tự đệ quy đơn giản, có lẽ đáng để nỗ lực sử dụng phép lặp rõ ràng hơn là hy vọng loại bỏ lệnh gọi đuôi.


Lỗi cuối cùng đã được chấp nhận. Nó nằm dưới sử thi: "Tính năng Yêu cầu Hài hòa". Hy vọng rằng điều đó có nghĩa là họ có kế hoạch thêm nó vào hỗ trợ ES6 trong V8.
Txangel

Bạn có thể bỏ phiếu cho hỗ trợ TCO trong Internet Explorer tại đây: wpdev.uservoice.com/forums/257854-internet-explorer-platform/…
Roy Tinker

12

Tối ưu hóa cuộc gọi đuôi sẽ được hỗ trợ trong chế độ nghiêm ngặt ECMAScript 6 trong tương lai. Kiểm tra http://www.2ality.com/2015/06/tail-call-optimization.html để biết chi tiết.

Kiểm tra http://kangax.github.io/compat-table/es6/ để biết hỗ trợ động cơ hiện tại.

Hiện tại (18-07-2019) các công cụ sau hỗ trợ tối ưu hóa cuộc gọi đuôi:

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

hỗ trợ nếu "các tính năng JavaScript thử nghiệm" -flag được bật:

  • Nút 6.5
  • Chrome 54 / Opera 41 Phiên bản hiện tại của bảng compat không liệt kê nó nữa

3

Tối ưu hóa cuộc gọi đuôi hiện có sẵn trong LispyScript được biên dịch sang JavaScript. Bạn có thể đọc thêm về nó ở đây .


Điều gì về đệ quy lẫn nhau?
cat

2

Hiện tại, không có triển khai JavaScript nào nhận dạng đệ quy đuôi. Các thay đổi đang được thực hiện trong ECMAScript 6 và như những người khác đã nói, có một vé mở trên V8 .

Tại đây, bạn có thể thấy trình hợp ngữ được tạo của V8 cho một hàm đệ quy đuôi:

Ví dụ về cách V8 biên dịch đệ quy

So sánh điều đó với cách Clang đã biên dịch cùng một hàm trong C

Ví dụ về đệ quy đuôi trình biên dịch C

V8 giữ lại lời gọi đệ quy, trong khi trình biên dịch C đã nhận dạng đệ quy đuôi và thay đổi nó thành một vòng lặp.


"Hiện tại không có triển khai JS nào nhận dạng đệ quy đuôi." đó là không chính xác như các Node 6.2.0, nhưng bạn gotta vượt qua một lá cờ
Janus Troelsen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.