由于函数的行为非常扭曲,我的代码出现了问题。
我使用google-api在BigQuery中传输数据。在Java中,您创建一个名为Bigquery.Tabledata.InsertAll
的对象(请求),然后执行它
TableDataInsertAllResponse response = request.execute();
(来自Google的示例代码)
但正如您所看到的,执行是在返回响应时产生副作用的事情。
我用Clojure(以分块方式)再现它
(defn load-bq
[client project-id dataset-id table-id data & {:keys [chunk-size] :or {chunk-size 500}}]
(let [chunks (partition-all chunk-size data)
_ (str "Now streaming data into table : [" project-id ":" dataset-id "." table-id "]")]
(map (partial atomic-load-bq client project-id dataset-id table-id) chunks)))
如果我尝试在repl中流式传输,它可以正常工作。但令人惊讶的是,doall在代码中不起作用,如let或with do。 这里有一个函数来说明原理
(def load-this-table
[... data]
(let [_ (doall (load-bq ... data))]
(load-bq ... data)
(do (load-bq ...data))))
此处不会加载任何内容。
我找到了一个有效的技巧,虽然它有点牵强:
(def load-this-table
[... data]
(let [_ (println (load-bq ... data))]
(println (load-bq ... data))))
这两行都将执行。当然我只需要一个流媒体,所以我在这里选择了一个解决方案。
如何在不使用println的情况下强制评估此代码? 我可以使用什么力评估behing println或任何更一般的核心功能。
我的印象是,差异并不是与懒惰有关,而是与Clojure和Java之间更为根本的区别有关。也许响应必须由客户“采取”。
谢谢!