2010-05-23 24 views
30

Tôi không thể sử dụng các hàm lôgic trên một loạt các phép toán trong Clojure (1.2). Cả các công trình sau đây do các chức năng logic là macro:"giảm" hoặc "áp dụng" bằng cách sử dụng các hàm lôgic trong Clojure

(reduce and [... sequence of bools ...]) 
(apply or [... sequence of bools ...]) 

Các thông báo lỗi nói rằng tôi "không thể lấy giá trị của một vĩ mô: #'clojure.core/and". Làm cách nào để áp dụng các hàm logic (macro) này mà không cần viết mã soạn sẵn?

Trả lời

50

Không sử dụng every?some để thay thế.

+0

Chính xác những gì tôi đang tìm kiếm. –

+6

Liên kết tới tài liệu, ['mọi?'] (Http://clojuredocs.org/clojure_core/clojure.core/every_q) và ['some'] (http://clojuredocs.org/clojure_core/clojure.core/some). –

+0

'một số' không hoạt động tốt cho' hoặc' khi nó trả về 'nil' nếu biểu thức sẽ đánh giá thành' false'. Sử dụng '# (một số? (Một số đúng?%))' Hoặc '# (không phải (mỗi? Sai?%))' Không thêm nhiều vào imo dễ đọc và cả hai không hoạt động quá tốt với các chuỗi-macro yêu cầu thêm parens xung quanh lambda. Ngoài ra 'một số?' Chỉ có sẵn từ v1.6. –

14

câu trả lời Michal của đã được tại chỗ trên, nhưng cách tiếp cận thay thế sau đây có thể hữu ích trong những tình huống tương tự như bất cứ khi nào bạn muốn sử dụng một macro như một chức năng:

(reduce #(and %1 %2) [... sequence of bools ...])

Về cơ bản bạn chỉ cần quấn vĩ mô trong một chức năng ẩn danh.

Có một vài lý do chính đáng để xem xét cách tiếp cận này:

  • Có những tình huống mà một chức năng tiện dụng như some hoặc every? không tồn tại
  • Bạn có thể có được hiệu suất tốt hơn (giảm có khả năng đem lại lợi ích từ một số tối ưu hóa rất tốt trong tương lai, ví dụ như áp dụng hàm trực tiếp cho một vector thay vì chuyển đổi vector thành một chuỗi)
+0

Điều này cũng có thể cho hiệu suất * tồi tệ hơn. 'reduce' * tính toán * câu trả lời từ toàn bộ chuỗi. 'mọi người?'trả về' false' ngay sau khi nó tìm thấy một phần tử sai. Trên máy tính của tôi, '(giảm # (và% 1% 2) (khuyết điểm nil (khoảng 100000000)))' mất vài giây, trong khi '(mỗi? Danh tính (cons nil (khoảng 100000000)))' trả về ngay lập tức. Chính thức, 'reduce' là thời gian tuyến tính, trong khi - cho bất kỳ xác suất nào có một phần tử giả,' mỗi? 'Là hằng số * trung bình *, mặc dù tuyến tính trong trường hợp xấu nhất. – Thumbnail

+1

@Thumbnail - rất đúng. Mặc dù tất nhiên bạn có thể nhận được tiền cứu trợ sớm với 'giảm' bằng cách sử dụng' giảm' nếu bạn muốn. Và nó không thay đổi thực tế rằng hiệu suất thô giảm là nhanh hơn: cho các công cụ như '(cho [v (vec (lặp lại 1000000 đúng))] (thời gian (mỗi? Nhận dạng v)))' tương đương giảm là khoảng 3x nhanh hơn trong việc khuấy động toàn bộ chuỗi, ví dụ. – mikera

+0

Nhưng điều đó chỉ hoạt động nếu bạn biết số đối số chính xác? –

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