2013-08-24 52 views
6

Có thể định nghĩa hai hàm trong clojure gọi đệ quy cho nhau không? Ví dụ, cặp này:Hai chức năng gọi nhau một cách đệ quy

(defn a [x] 
    (if (= 0 x) 0 (b (dec x)))) 

(defn b [x] 
    (if (= 0 x) 0 (a (dec x)))) 

Compilation không thành công với:

Unable to resolve symbol: b in this context 

Kể từ khi tôi chưa xác định b khi tôi cố gắng gọi nó trong a.

ví dụ, trong ruby ​​này hoạt động tốt:

def a(x) 
    x == 0 ? x : b(x-1) 
end 

def b(x) 
    x == 0 ? x : a(x-1) 
end 

Trả lời

6

một trong hai:

(declare b) ...; phần còn lại của mã của bạn sau đó có thể được sử dụng như là

hay:

(def mutual 
(letfn [(a [ ... ] ...) 
     (b [ ... ] ...)] 
    [a b])) 

(def a (first mutual)) 
(def b (second mutual)) 
+0

Làm cho tinh thần, đoán có một sự cân bằng cho tốc độ biên dịch mà nó không thể nhìn về phía trước cho các định nghĩa chức năng. Nhờ câu trả lời đã xóa cho liên kết này tới tài liệu (http://clojuredocs.org/clojure_core/clojure.core/declare) – spike

+0

Sự cân bằng không dành cho tốc độ biên dịch, nhưng lại gặp lỗi. Cũng có hàm 'resolve' khi hai không gian tên cần tham khảo lẫn nhau. – noisesmith

+0

Bạn có liên kết để biết thêm thông tin về điều đó không? Những loại lỗi nào đang bị tránh bởi trình biên dịch bỏ qua các định nghĩa hàm rõ ràng? – spike

6

Tùy thuộc vào việc thực hiện mã của bạn, hãy nhớ rằng bạn có thể nhận stack overflow ngoại lệ.

Có chức năng (clojure.core/trampoline) đi vào vở kịch và thực hiện phép thuật của nó.

tấm bạt lò xo có thể được sử dụng để chuyển đổi thuật toán yêu cầu lẫn nhau đệ quy mà không cần tiêu thụ ngăn xếp. Cuộc gọi f với args được cung cấp, nếu bất kỳ. Nếu f trả về fn, gọi fn không có đối số và tiếp tục lặp lại, cho đến khi giá trị trả về không phải là fn, thì trả về giá trị không phải là fn đó. Lưu ý rằng nếu bạn muốn trả về giá trị cuối cùng là , bạn phải bọc nó trong một số cấu trúc dữ liệu và giải nén nó sau khi trả về tấm bạt lò xo.

+0

ha! bài đăng blog đầu tiên tôi tìm thấy về điều này thậm chí còn sử dụng các chức năng ví dụ của tôi: http://pramode.net/clojure/2010/05/08/clojure-trampoline/ – spike