2015-06-09 34 views
6

Giả sử bạn có một hàm đệ quy như:Đây có phải là cuộc gọi đuôi không? (Javascript)

Blah.prototype.add = function(n) { 
    this.total += n; 
    this.children.forEach(function(child) { 
     child.add(n); 
    }); 
}; 

child.add() một cuộc gọi đuôi? Nếu không nó có thể được viết như vậy nó được?

+0

Tôi sẽ nói như vậy. Mặc dù nó nằm trong vòng lặp, nó vẫn là hành động cuối cùng được thực hiện. – Brennan

+0

Tôi không chắc ... Tôi đang nghĩ về một vòng lặp 'for (i = 0; i pixelmike

+0

Có lẽ một 'đuôi gọi' trong JS sẽ làm cho việc sử dụng' return someFn() 'cũng cho phép hàm initator thu gom rác. –

Trả lời

1

Vâng, đó là một cuộc gọi đuôi:

function(child) { 
    child.add(n); 
//^tail 
} 

Tuy nhiên, không có gì ở đây là đệ quy đuôi, bởi vì nó không phải là một cuộc gọi đệ quy trực tiếp.

Ngoài ra this.children.forEach(…) là cuộc gọi đuôi trong phương thức add.

Tuy nhiên, yêu cầu gọi lại trong phương thức gốc forEach có thể không được tối ưu hóa cho cuộc gọi đuôi (và tất cả trừ khi cuộc gọi cuối cùng không thể là anyway). Bạn có thể ép buộc bằng cách viết lại hàm của mình thành

Blah.prototype.add = function(n) { 
    "use strict"; 
    this.total += n; 
    let l = this.children.length; 
    if (!l--) 
     return; 
    for (let i=0; i<l; i++) 
     this.children[i].add(n); 
    this.children[i].add(n); // tail-recursion 
}; 

Lưu ý rằng không có cuộc gọi đuôi nào được tối ưu hóa nếu bạn cũng không return kết quả của chúng.

+0

Bạn có chắc 'add' là đệ quy đuôi không? Ngay cả khi một cấu trúc vòng lặp đơn giản được sử dụng, hoạt động mới nhất được thực hiện sẽ là kiểm tra vòng lặp có điều kiện, do đó sẽ không được đệ quy đuôi, phải không?Tôi nghĩ rằng các cuộc gọi đệ quy phải là biểu thức thực hiện mới nhất cho một thuật toán được đuôi đệ quy. – plalx

+0

@plalx: Tôi không nói 'add' có đuôi đệ quy. Nếu ở tất cả thì nó đệ quy với 'forEach' và gọi lại của nó - nó không tự gọi nó. Tôi chỉ nói rằng 'add' chứa một cuộc gọi đuôi. – Bergi

+0

Cảm ơn, vâng tôi phải rõ ràng rằng tôi đã hỏi nếu child.add là một cuộc gọi đuôi cho các chức năng thêm, không phải forEach gọi lại. – pixelmike

1

Are any Javascript engines tail call optimized?

JavaScript như hiện nay sẽ không tối ưu hóa cho rằng

tùy chọn khác sẽ là một tấm bạt lò xo https://taylodl.wordpress.com/2013/06/07/functional-javascript-tail-call-optimization-and-trampolines/

+0

Vâng, tôi đã không nghĩ rằng tối ưu hóa đã được đặt ra, nhưng tôi đang cố gắng chuẩn bị cho nó khi nào. Cảm ơn các liên kết. – pixelmike

+0

Câu hỏi mà bạn đã liên kết đã lỗi thời. ES6 có tối ưu hóa cuộc gọi đuôi thích hợp. – Bergi

+0

Hãy sửa tôi nếu tôi sai nhưng ES6 vẫn chưa ra? – exussum

Các vấn đề liên quan