2013-05-02 74 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