2009-10-27 56 views
2

我正在使用消息傳遞工具包(它恰巧是Spread,但我不知道細節問題)。從此工具包接收消息需要一些樣板文件:將此Clojure調用轉換爲懶惰序列

  1. 創建到守護程序的連接。
  2. 加入羣組。
  3. 接收一條或多條消息。
  4. 離開組。
  5. 斷開守護進程。

下面是我見過使用elsewhere一些成語,我能煮了採用擴展的Java API和Clojure的互操作形式的一些工作職能:

(defn connect-to-daemon 
    "Open a connection" 
    [daemon-spec] 
    (let [connection (SpreadConnection.) 
     {:keys [host port user]} daemon-spec] 
    (doto connection 
     (.connect (InetAddress/getByName host) port user false false)))) 

(defn join-group 
    "Join a group on a connection" 
    [cxn group-name] 
    (doto (SpreadGroup.) 
    (.join cxn group-name))) 

(defn with-daemon* 
    "Execute a function with a connection to the specified daemon" 
    [daemon-spec func] 
    (let [daemon (merge *spread-daemon* daemon-spec) 
     cxn (connect-to-daemon daemon-spec)] 
    (try 
    (binding [*spread-daemon* (assoc daemon :connection cxn)] 
     (func)) 
    (finally 
     (.disconnect cxn))))) 

(defn with-group* 
    "Execute a function while joined to a group" 
    [group-name func] 
    (let [cxn (:connection *spread-daemon*) 
     grp (join-group cxn group-name)] 
    (try 
    (binding [*spread-group* grp] 
     (func)) 
    (finally 
     (.leave grp))))) 

(defn receive-message 
    "Receive a single message. If none are available, this will block indefinitely." 
    [] 
    (let [cxn (:connection *spread-daemon*)] 
    (.receive cxn))) 

(基本上相同的成語爲with-open,剛纔說的SpreadConnection類使用的,而不是disconnectclose。格兒。還有,我留下了一些宏不相關的結構性問題在這裏。)

此作品不夠好。我可以調用從結構的內部接收消息,如:

(with-daemon {:host "localhost" :port 4803} 
    (with-group "aGroup" 
    (... looping ... 
     (let [msg (receive-message)] 
     ...)))) 

它發生,我認爲receive-message將是清潔器,如果它是一個無限懶惰序列產生的消息使用。所以,如果我想加入羣,並得到消息,調用代碼應該是這個樣子:

(def message-seq (messages-from {:host "localhost" :port 4803} "aGroup")) 
(take 5 message-seq) 

我見過很多懶惰序列的例子不清理,這不是太難。該捕獲是從上面的步驟#4和5:離開組並從守護進程斷開連接。如何將連接和組的狀態綁定到序列當不再需要序列時運行必要的清理代碼?

回答

6

This本文描述瞭如何使用clojure-contrib填充隊列完成該操作。關於清理 - 關於填充隊列的整潔的事情是,你可以提供一個阻塞功能,如果出現錯誤或達到某種情況,可以自行清理。您也可以持有對資源的引用以在外部控制它。序列將會終止。因此,根據您的語義要求,您必須選擇適合的策略。

3

試試這個:

(ns your-namespace 
    (:use clojure.contrib.seq-utils)) 

(defn messages-from [daemon-spec group-name] 
    (let [cnx (connect-to-deamon daemon-spec)) 
     group (connect-to-group cnx group-name)] 
    (fill-queue (fn [fill] 
        (if done? 
         (do 
         (.leave group) 
         (.disconnect cnx) 
         (throw (RuntimeException. "Finished messages")) 
         (fill (.receive cnx)))))) 

集做了什麼?當您想要終止列表時爲true。此外,(.receive cnx)中引發的任何異常也將終止列表。