2013-05-02 71 views
1

可以說我想在clojure中打印hbase表掃描的輸出。Clojure和HBase:通過掃描迭代懶惰

(defmulti scan (fn [table & args] (map class args))) 

(defmethod scan [java.lang.String java.lang.String] [table start-key end-key] 
    (let [scan (Scan. (Bytes/toBytes start-key) (Bytes/toBytes end-key))] 
     (let [scanner (.getScanner table scan)] 
      (doseq [result scanner] 
       (prn 
        (Bytes/toString (.getRow result)) 
        (get-to-map result)))))) 

其中get-to-map將結果變成地圖。它可以像這樣運行:

(hbase.table/scan table "key000001" "key999999") 

但是如果我想讓用戶對掃描結果做些什麼呢?我可以允許他們傳遞一個函數作爲回調應用於每個結果。但我的問題是:我該怎麼回報,如果我希望用戶能夠在每個結果

(Bytes/toString (.getRow result)) 
(get-to-map result) 

不能保留以前的結果,因爲可能與懶惰的一個簡單的執行力度發生懶洋洋地迭代-seq。

回答

1

如果你接受一個回調參數,你可以把它叫做doseq內:

(defmulti scan [f table & args] (mapv class args)) ; mapv returns vector 

(defmethod scan [String String] [f table start-key end-key] 
       ; ^- java.lang classes are imported implicitly 
    (let [scan ... 
     scanner ...] ; no need for two separate lets 
    (doseq [result scanner] 
     ; call f here, e.g. 
     (f result)))) 

這裏f將每個結果調用一次。其返回值以及結果本身將立即丟棄。您當然可以用result的一些預處理版本,例如f來調用。 (f (foo result) (bar result))

您也可以將結果的序列/向量返回給客戶端,並讓它自己處理。如果序列是懶惰的,則需要確保支持它的任何資源在處理期間保持打開狀態(並且可能稍後關閉它們 - 請參見with-open;處理代碼需要在with-open內執行並完成並在返回時進行處理)。

例如,預處理結果的矢量返回給客戶端,你可以做

(defmethod scan ... 
    (let [...] 
    (mapv (fn preprocess-result [result] 
      (result->map result)) 
      scanner))) 

然後,客戶機可以做任何它想要與他們。改用map來返回一個懶惰序列。如果客戶需要打開/關閉資源,則可以將其作爲參數進行掃描,以便客戶端可以說

(with-open [r (some-resource)] 
    ; or mapv, dorun+map, doall+for, ... 
    (doseq [result (scan r ...)] 
    (do-stuff-with result))) 
+0

感謝。我現在正在返回一個函數,調用結果掃描器上的下一個函數,直到它耗盡爲止 '#(let [result(.next result-scanner)] (if(not = result nil) [(Bytes/toString(.getRow result))(get-to-map result)] nil))' 接下來我在理解的工作就是如何簡潔地調用這個函數,直到它返回nil,然後發生。 '(let [cursor(hbase.table/scan table「k1」「r2」)] ...)' – 2013-05-02 01:01:02

+0

btw。感謝您的java.lang.String - >字符串擡頭 – 2013-05-02 01:02:25

+0

當然。我編輯了答案,添加了兩個如何將預處理結果傳遞給客戶端的例子。在Clojure中,將一個集合 - 通常是一個懶惰的序列 - 返回給客戶端通常比使用Java迭代器或任何工作集合更爲常見。另一種解決方案是返回一個減速器;您需要使用Clojure 1.5,但是您可以使用'r/map'進行預處理,讓客戶端自己創建'r/map'(或其他),並且不用擔心中間分配問題。代碼的一般感覺保持非常相似。 – 2013-05-02 01:09:52