2010-08-22 62 views
12

Ok Đây là những gì tôi đang cố gắng để làmclojure chức năng trì hoãn thực hiện

(defn addresses [person-id] 
;addresses-retrival) 

(defn person [id] 
    (merge {:addresses (addresses id)} {:name "john"})) 

Trong chức năng người ở trên tôi muốn địa chỉ để được lấy ra chỉ theo yêu cầu, như khi tôi làm

(:addresses (person 10)) 

và không phải khi

(person 10) 

Tôi không chắc chắn liệu tôi có đi đúng về vấn đề này hay không.

Trả lời

10

Bạn có thể sử dụng độ trễ.

(defn person [id] 
    (delay {:addresses (addresses id) :name "john"})) 

(người 2) sau đó sẽ trở lại bị trì hoãn mà không đánh giá bất cứ điều gì. Để truy cập nội dung và đánh giá đối tượng bị trì hoãn, hãy sử dụng lực hoặc deref (hoặc @).

(:addresses @(person 5)) 

Hoặc, bạn chỉ có thể trì hoãn địa chỉ.

(defn person [id] 
    {:addresses (delay (addresses id)) :name "john"}) 

có thể đẹp hơn tùy thuộc vào sự cố của bạn.

Nó cho phép xác định:

(defn get-address [person] 
    @(:address person)) 

nào sẽ nhận được địa chỉ trì hoãn và buộc nó. (Bắt buộc có nghĩa là tính toán lần đầu tiên và truy xuất kết quả bắt buộc bất kỳ lúc nào khác).

+0

cảm ơn bạn rất nhiều .Tôi đã tự hỏi nếu điều này có thể được thực hiện minh bạch để nó có thể được đánh giá lần đầu tiên nó được sử dụng. Thay vì buộc đánh giá theo cách thủ công? – Surya

+0

Tôi không nghĩ vậy. Clojure rõ ràng là lười biếng và ép buộc, theo như tôi biết. –

+0

lazymap của tôi [thư viện] (http://bitbucket.org/kotarak/lazymap) thực hiện chính xác điều đó. Nó cung cấp các trình đơn thả xuống trong suốt cho tất cả các loại bản đồ, chỉ tính giá trị của chúng trong trường hợp chúng thực sự được truy xuất. – kotarak

1

Ít nhất theo như trình tự đi, clojure là khá damned lười biếng mà không cần phải nói.

Ở đây, mô hình hóa address-hồi của bạn như đếm, hãy thử:

(defn addresses [person-id] 
    (iterate #(do (println %) (inc %)) person-id)) 

(defn person [id] 
    (merge {:addresses (addresses id)} {:name "john"})) 

(def people (map person (range 100))) 

Cho đến nay nó sẽ không có bất cứ điều gì được in, nhưng nếu bạn nói:

(doall (take 5 (:addresses (nth people 10)))) 

Sau đó, bạn sẽ thấy in ấn xảy ra trong chính xác các trường hợp cần phải xảy ra để đếm lên năm ở vị trí thứ mười. Tôi tưởng tượng đó có thể là loại hành vi bạn muốn?

Vì vậy, nhận tra cứu địa chỉ của bạn để tạo ra một chuỗi lười biếng (bản đồ, bộ lọc, giảm tất cả sẽ làm)

0

Tôi có thể đề nghị một cái gì đó gần với những gì bạn mong đợi.

; Note the use of anonymouns function. #(addresses id) 
(defn person [id] 
    (merge {:addresses #(addresses id)} {:name "john"})) 

; :addresses returns a function. Evaluate it by wrapping it in another set of parans. 
((:addresses (person 10))) 
1

Bạn có thể trả về hàm từ hàm addresses khi sau này được gọi sẽ truy xuất địa chỉ. Một cái gì đó như thế này:

(defn addresses [person-id] 
#(;addresses-retrival)) 

(defn person [id] 
    (merge {:addresses ((addresses id))} {:name "john"})) 

Note hơn addresses hàm trả về một chức năng ẩn danh (được tạo ra sử dụng #) và person chức năng gọi rằng chức năng ẩn danh sử dụng thêm một cặp dấu ngoặc.

0

Hãy nhớ rằng sự chậm trễ được ghi nhớ, do đó, các cuộc gọi liên tiếp của các địa chỉ của bạn bị chậm trễ sẽ luôn mang lại cùng một địa chỉ như lần đầu tiên bạn hủy đăng ký trễ.

(defn addresses [person-id] 
    {:home (str (rand-int 100) " Cool St.") :work "1243 Boring St."}) 

(defn person [id] 
    (merge {:addresses (delay (addresses id))} {:name "john"})) 

(let [person1 (person 1)] 
    (println @(:addresses person1)) 
    (println @(:addresses person1))) 

này sẽ in:

{:home 65 Cool St., :work 1243 Boring St.} 
{:home 65 Cool St., :work 1243 Boring St.} 

Thông báo như thế nào địa chỉ nhà là không thay đổi trên deref thứ hai của sự chậm trễ.

Nếu bạn không muốn hành vi này, bạn cần phải sử dụng chức năng đóng để thay thế.

(defn addresses [person-id] 
    {:home (str (rand-int 100) " Cool St.") :work "1243 Boring St."}) 

(defn person [id] 
    (merge {:addresses (fn [] (addresses id))} {:name "john"})) 

(let [person1 (person 1)] 
    (println ((:addresses person1))) 
    (println ((:addresses person1)))) 

này sẽ in:

{:home 16 Cool St., :work 1243 Boring St.} 
{:home 31 Cool St., :work 1243 Boring St.} 

Thông báo như thế nào địa chỉ nhà là khác nhau về các cuộc gọi tiếp theo; đến việc đóng cửa.

Vì vậy, nếu bạn đang sử dụng chức năng addresses, hãy tìm nạp địa chỉ từ cơ sở dữ liệu. Và những người có thể thay đổi địa chỉ của họ và bạn muốn mã của mình luôn có địa chỉ mới nhất, đó là điều cần ghi nhớ nếu Delay hoạt động cho bạn hoặc nếu đóng cửa chức năng sẽ là ứng cử viên tốt hơn.

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