Mô tả về thuật toán của bạn thực sự quá mơ hồ để đánh giá nó vào thời điểm này. Nhưng, đây là một số điều cần xem xét.
CPS
Trong thực tế, có một cách để chuyển đổi bất kỳ mã nào thành một hình thức chỉ sử dụng các cuộc gọi đuôi. Đây là biến đổi CPS. CPS ( Kiểu tiếp tục truyền ) là một hình thức thể hiện mã bằng cách truyền cho mỗi chức năng một phần tiếp theo. Tiếp tục là một khái niệm trừu tượng đại diện cho "phần còn lại của một phép tính". Trong mã được biểu thị dưới dạng CPS, cách tự nhiên để xác định lại phần tiếp theo là một hàm chấp nhận một giá trị. Trong CPS, thay vì một hàm trả về một giá trị, thay vào đó, nó áp dụng hàm đại diện cho sự tiếp tục hiện tại với chức năng "được trả về" của hàm.
Ví dụ, hãy xem xét chức năng sau:
(lambda (a b c d)
(+ (- a b) (* c d)))
Điều này có thể được thể hiện trong CPS như sau:
(lambda (k a b c d)
(- (lambda (v1)
(* (lambda (v2)
(+ k v1 v2))
a b))
c d))
Nó xấu, và thường chậm, nhưng nó có một số lợi thế nhất định:
- Việc chuyển đổi có thể hoàn toàn tự động. Vì vậy, không cần phải viết (hoặc xem) mã ở dạng CPS.
- Kết hợp với thunking và trampolining , nó có thể được sử dụng để cung cấp tối ưu hóa cuộc gọi đuôi trong các ngôn ngữ không cung cấp tối ưu hóa cuộc gọi đuôi. (Tối ưu hóa cuộc gọi đuôi của các hàm đệ quy trực tiếp có thể được thực hiện thông qua các phương tiện khác, chẳng hạn như chuyển đổi cuộc gọi đệ quy thành một vòng lặp. Nhưng đệ quy gián tiếp không phải là tầm thường để chuyển đổi theo cách này.)
- Với CPS, các phần tiếp theo trở thành một đối tượng hạng nhất. Vì các phần tiếp theo là bản chất của điều khiển, điều này cho phép hầu như bất kỳ toán tử điều khiển nào được triển khai như một thư viện mà không cần bất kỳ sự hỗ trợ đặc biệt nào từ ngôn ngữ. Ví dụ, goto, ngoại lệ và phân luồng hợp tác đều có thể được mô hình hóa bằng cách sử dụng các phần tiếp theo.
TCO
Dường như với tôi rằng lý do duy nhất liên quan đến đệ quy đuôi (hay gọi chung là đuôi) là cho mục đích tối ưu hóa cuộc gọi đuôi (TCO). Vì vậy, tôi nghĩ rằng một câu hỏi tốt hơn để hỏi là "mã năng suất chuyển đổi của tôi có thể tối ưu hóa cuộc gọi đuôi không?".
Nếu chúng ta một lần nữa xem xét CPS, một trong những đặc điểm của nó là mã được thể hiện trong CPS chỉ bao gồm các lệnh gọi đuôi. Vì mọi thứ đều là cuộc gọi đuôi, chúng tôi không cần lưu điểm trả về ngăn xếp. Vì vậy, tất cả các mã ở dạng CPS phải được tối ưu hóa cuộc gọi, phải không?
Vâng, không hoàn toàn. Bạn thấy đấy, mặc dù có vẻ như chúng ta đã loại bỏ ngăn xếp, tất cả những gì chúng ta đã làm chỉ là thay đổi cách chúng ta đại diện cho nó. Ngăn xếp bây giờ là một phần của việc đóng cửa đại diện cho sự tiếp nối. Vì vậy, CPS không kỳ diệu làm cho tất cả các cuộc gọi đuôi của chúng tôi được tối ưu hóa.
Vì vậy, nếu CPS không thể tạo ra mọi thứ TCO, thì có một biến đổi cụ thể cho đệ quy trực tiếp có thể không? Không, không nói chung. Một số thu hồi là tuyến tính, nhưng một số thì không. Thu hồi phi tuyến tính (ví dụ, cây) đơn giản là phải duy trì một lượng trạng thái khác nhau ở đâu đó.