Tôi đang cố gắng hiểu cách thức thành ngữ trong Clojure để recurse thông qua một cây hoặc danh sách được đại diện bởi một danh sách Clojure (hoặc một loại bộ sưu tập).Cách thành ngữ để recurse thông qua các bộ sưu tập trong Clojure
tôi có thể viết như sau để đếm các yếu tố trong một bộ sưu tập phẳng (bỏ qua một thực tế rằng nó không phải đuôi-đệ quy):
(defn length
([xs]
(if (nil? (seq xs))
0
(+ 1 (length (rest xs))))))
Bây giờ trong Đề án hoặc CL tất cả các ví dụ duy nhất từng làm điều này qua danh sách , do đó, kiểm tra trường hợp cơ sở thành ngữ trong các ngôn ngữ đó sẽ là (nil? xs)
. Trong Clojure, chúng tôi muốn chức năng này hoạt động trên tất cả các loại bộ sưu tập, vì vậy là thử nghiệm thành ngữ (nil? (seq xs))
hoặc có thể là (empty? xs)
hoặc một thứ hoàn toàn khác?
Trường hợp khác tôi muốn xem xét là duyệt qua cây, tức là duyệt qua danh sách hoặc vectơ đại diện cho một cây, ví dụ: [1 2 [3 4]
.
Ví dụ, đếm các nút trong một cây:
(defn node-count [tree]
(cond (not (coll? tree)) 1
(nil? (seq tree)) 0
:else (+ (node-count (first tree)) (node-count (rest tree)))))
Ở đây chúng ta sử dụng (not (coll? tree))
để kiểm tra các nguyên tử, trong khi ở Scheme/CL, chúng tôi muốn sử dụng atom?
. Chúng tôi cũng sử dụng (nil? (seq tree))
để kiểm tra bộ sưu tập trống. Và cuối cùng chúng tôi sử dụng first
và rest
để hủy cấu trúc cây hiện tại sang nhánh trái và phần còn lại của cây.
Vì vậy, để tóm tắt, là những hình thức sau đây thành ngữ trong Clojure:
(nil? (seq xs))
để kiểm tra bộ sưu tập trống(first xs)
và(rest xs)
để thâm nhập vào các bộ sưu tập(not (coll? xs))
để kiểm tra các nguyên tử
Cảm ơn câu trả lời của bạn. Về 'rest' /' next', vì vậy bạn đang nói tôi nên sử dụng '(length (next xs))' trong lời gọi đệ quy, bởi vì tôi sẽ gọi 'seq' trên bộ sưu tập? Đối với 'coll? ', Tại thời điểm này, tôi chỉ quan tâm đến các loại bộ sưu tập Clojure bản địa, vì vậy' coll? 'Nên làm cho tôi tốt. – liwp
Bạn được chào đón. Tôi chủ yếu có nghĩa là gọi 'seq' trên giá trị trả về của' rest' trực tiếp (ví dụ: '(if-let [new-xs (seq (phần còn lại xs))] ...)'), thành ngữ chắc chắn là '(tiếp theo xs) 'và' recur'ing với 'phần còn lại', điều này chỉ có nghĩa nếu bạn thực sự không thể gọi' seq' trên giá trị trả về trong lần lặp tiếp theo. Trong trường hợp hàm 'length' của bạn, tôi có thể vẫn sử dụng' next' để làm cho nó rõ ràng nhất có thể là hàm này là nghiêm ngặt, nhưng tôi muốn nói nó không tạo ra sự khác biệt nhiều. –
Ok, tôi hiểu - có ý nghĩa. – liwp