2012-08-11 36 views
5

Giả sử bạn có ba chức năng của arity 1, 2 và 3 như sau:Clojure có thể đánh giá một chuỗi các chức năng phối hợp hỗn hợp và trả về một phần chức năng nếu cần?

(defn I [x] x) 
(defn K [x y] x) 
(defn S [x y z] (x z (y z))) 

Liệu clojure có chức năng thẩm định hoặc thành ngữ để đánh giá:

(I K S I I) as (I (K (S (I (I))))) 

trở về một hàm parital của arity 2?

Tôi đang xem xét việc tạo macro có thể lấy các định nghĩa hàm đơn giản ở trên và mở rộng chúng thành các hàm đa hàm có thể trả về một phần kết quả. Tôi sẽ không muốn tạo macro nếu đã có một cách tích hợp hoặc thành ngữ để thực hiện việc này.

Đây là những gì các macro mở rộng muốn cho các chức năng trên:

(defn I 
    ([x] I x) 
    ([x & more] (apply (I x) more))) 

(defn K 
    ([x] (partial K x)) 
    ([x y] x) 
    ([x y & more] (apply (K x y) more))) 

(defn S 
    ([x] (partial S x)) 
    ([x y] (partial S x y)) 
    ([x y z] (x z (y z))) 
    ([x y z & more] (apply (S x y z) more))) 
+0

Chỉ tìm thấy điều này, và nghĩ rằng nó * có thể * hoàn hảo cho bạn, và nếu không có gì khác, ít nhất là hữu ích ... http: //alfredodinapoli.wordpress.com/2011/03/16/a-bit-of -clojure-magic-and-high-order-functions-được-phục vụ/ –

Trả lời

5

Tôi không chắc tôi hoàn toàn hiểu những gì bạn đang cố gắng để làm, nhưng comp chức năng rất hữu ích để làm loại "chức năng chuỗi" bạn dường như đang nói về. Ví dụ:

user> ((comp vec rest list) 1 2 3 4 5) 
=> [2 3 4 5] 

Đó là tương đương với:

user> (vec (rest (list 1 2 3 4 5))) 
=> [2 3 4 5] 

Trong trường hợp của bạn, nếu bạn có danh sách (I K S I I), và bạn muốn đánh giá nó như (I (K (S (I (I))))), tôi sẽ sử dụng (reduce comp ...), nhưng bạn có thể cũng sử dụng (apply comp ...).

user> ((reduce comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 
user> ((apply comp [vec rest list]) 1 2 3 4 5) 
=> [2 3 4 5] 

Bạn cũng có thể quan tâm đến các macro -> hoặc ->>. Các macro này lồng các đối số của chúng tuần tự vào các đối số tiếp theo. Macro -> sẽ lồng vào vị trí đầu tiên của biểu thức tiếp theo, trong khi macro ->> sẽ lồng vào vị trí cuối cùng của biểu thức tiếp theo. Nếu "điều tiếp theo" là một hàm, cả hai sẽ hoạt động giống nhau, và tạo thành một biểu thức của (function nested-things-so-far) và tiếp tục.

Thực sự, ví dụ là tốt nhất:

(-> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- (+ 1 10) 100)) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> -88 

(->> 1 (+ 10) (- 100) inc) 
;//Expands to... 
(inc (- 100 (+ 10 1))) 
;//Evaluating in the REPL... 
user> (-> 1 (+ 10) (- 100) inc) 
=> 90 

Tuy nhiên, nó có vẻ giống như bạn muốn làm điều gì đó liên quan đến tự động currying (mặc dù, một lần nữa, tôi không nghĩ rằng tôi hoàn toàn hiểu), và cho rằng Tôi không biết bất kỳ thứ gì đã có sẵn.

+0

Cảm ơn bạn đã trả lời câu hỏi này. Nó sẽ đưa tôi một thời gian để grok và xem nếu nó có thể đơn giản hóa những gì tôi đang làm kể từ khi tôi mới để clojure và lập trình loại lisp. Đôi khi tôi biết những gì tôi muốn làm nhưng không biết nó được gọi là gì và ngay cả khi tôi có một cụm từ tìm kiếm tốt, kết quả cho việc che dấu rất hạn chế. Chỉ cần tìm ra rằng những gì tôi đang cố gắng để làm có thể được gọi là "tự động currying" là một trợ giúp lớn. – dansalmo