2014-05-15 56 views
0

我正在使用一個代理,它引用一組來跟蹤我需要通知事件的用戶。我希望它會自動初始化在第一時間其所謂的,所以這是我迄今所做的:Clojure - 如何自動初始化一次

(declare notify-users!) 

(def users-to-notify 
    (future 
    (def _utn (agent #{})) 
    (add-watch _utn :utn notify-users!) 
    _utn)) 

(defn update-user [user-id] 
    (send-off @users-to-notify conj user-id)) 

(defn notify-users! [key reference old-state new-state] 
    (println old-state " -> " new-state)) 

這似乎是工作,但我不知道它有這種方法的任何問題,我我不知道。

+1

defonce應該工作 – KobbyPemson

+0

重要的是它不被初始化之前它被稱爲? –

+0

這並不重要;我只是不擔心它。 – pickwick

回答

1

我自己還是個學習者,但我想我可以幫助你以更習慣的方式表達你正在寫的東西。

首先,在開始使用它們之前獲取定義的幫助函數,除非有特定的原因讓您想要首先聲明它們。我用這種方式測試了代碼,多次並且它工作正常。

(defn notify-users [key reference old-state new-state] 
    (println old-state " -> " new-state)) 

(defonce users-to-notify 
    (future 
    (let [utn (agent #{})] 
    (add-watch utn :utn notify-users) 
    utn))) 

(defn update-user! [user-id] 
    (send-off @users-to-notify conj user-id)) 

而且,也許它是一個風格問題,但我通常只在頂級高清使用,以免有關範圍的下一個程序員通過我的讀碼混淆。 let在這種情況下更好,如果您測試它,您會看到代理在用戶通知變量中保持不變。感嘆號用於指示變異函數,而不是副作用函數,並且通常下劃線用於指示作爲參數傳遞給函數的值,該參數不會在結果代碼中使用。一個常見的例子可以在使用dotimes功能被發現,需要結合:

(dotimes [_ 10] (println "I'm a cheeky monkey!")) 

我也改變了高清到defonce,但你要注意,defonce不是線程安全的,這意味着EXPR可以得到評估多次。

+0

使用未來的重點在於,初始狀態只創建一次,即第一次被調用。我在運行代碼時沒有遇到任何錯誤。 – pickwick

+0

你能否使用承諾? (未來(傳遞通知用戶!(fn [key reference old-state new-state]) (println old-state「 - >」新狀態))))' – kurofune

+0

我編輯了我的答案,請檢查它,看看它是否有幫助。另外,我對deref的評論不好。我沒有意識到你在發送時使用它來讓代理脫離未來。當我第一次運行它時,它在我的機器上拋出一個錯誤,但是當我重新裝入我的repl時,它像你說的那樣運行正常。 – kurofune