Clojure không tự thực hiện tối ưu hóa cuộc gọi đuôi: khi bạn có chức năng đệ quy đuôi và bạn muốn tối ưu hóa nó, bạn phải sử dụng biểu mẫu đặc biệt recur
. Tương tự, nếu bạn có hai hàm đệ quy lẫn nhau, bạn chỉ có thể tối ưu hóa chúng bằng cách sử dụng trampoline
.
Trình biên dịch Scala có thể thực hiện TCO cho một hàm đệ quy, nhưng không phải cho hai hàm đệ quy lẫn nhau.
Bất cứ khi nào tôi đọc về những hạn chế này, chúng luôn được gán cho một số giới hạn nội tại đối với mô hình JVM. Tôi không biết gì nhiều về trình biên dịch, nhưng điều này đánh đố tôi một chút. Hãy để tôi lấy ví dụ từ Programming Scala
. Đây là chức năng
def approximate(guess: Double): Double =
if (isGoodEnough(guess)) guess
else approximate(improve(guess))
được dịch sang
0: aload_0
1: astore_3
2: aload_0
3: dload_1
4: invokevirtual #24; //Method isGoodEnough:(D)Z
7: ifeq
10: dload_1
11: dreturn
12: aload_0
13: dload_1
14: invokevirtual #27; //Method improve:(D)D
17: dstore_1
18: goto 2
Vì vậy, ở cấp độ mã byte, người ta chỉ cần goto
. Trong trường hợp này, trên thực tế, công việc khó khăn được thực hiện bởi trình biên dịch.
Cơ sở nào của máy ảo cơ bản sẽ cho phép trình biên dịch xử lý TCO dễ dàng hơn?
Là một lưu ý phụ, tôi không mong đợi các máy thực tế sẽ thông minh hơn JVM. Tuy nhiên, nhiều ngôn ngữ biên dịch thành mã gốc, chẳng hạn như Haskell, dường như không có vấn đề gì với việc tối ưu hóa các cuộc gọi đuôi (tốt, đôi khi Haskell có thể có do sự lười biếng, nhưng đó là một vấn đề khác).