我想知道在Clojure中实现数据封装的惯用方法是什么。下面,我描述了我的特定用例,以激发我提供的示例代码。
我在dbaccess模块中有代码,它执行一个复杂的数据库查询,从数据库中获取一些数据。我还有一些函数对返回的原始数据进行操作。然后,这些函数提供了对数据的更处理、更精细的视图,并使用来自系统中其他模块的不同参数多次调用。让我们称它们为"API函数“。
查询很重,应该在开始时只执行一次,然后API函数将对内存中的原始数据进行操作,而不必执行另一个DB查询。
下面是我使用闭包的方法:
dbaccess模块
(ns dbaccess)
(let
[raw-data (complex-database-query)]
(defn create-client-names []
(fn [some-args] raw-data))
(defn create-client-portfolio []
(fn [some-args] raw-data))
(defn create-client-stocks []
(fn [some-args] raw-data)))其他客户端模块
(def client-names (create-client-names))
(doall (map println (client-names "Baltimore")))我不喜欢为捕获原始数据的创建函数命名。
更重要的是,上面的代码不允许客户端模块在查询执行之前配置查询的各个方面(例如数据库连接信息)。
另一方面,如果不使用闭包,我必须在dbaccess模块和其他需要调用API函数的模块之间显式地传递原始数据。有更好的办法吗?我是否应该在dbaccess模块中使用可变状态?
发布于 2013-03-22 16:05:25
我必须在dbaccess模块和其他需要调用API函数的模块之间显式地传递原始数据。
应该这样做,显式地传递函数所需的数据,因为:
发布于 2013-03-22 19:12:25
我想在这种情况下你不需要let:
(def ^:private raw-data (promise))
(future (deliver raw-date (complex-database-query))) ;; A. Webb mentioned this
(defn create-client-names []
(fn [some-args] @raw-data))
...为什么create-client-names和其他函数不只是
(defn create-client-names [some-args]
@raw-data)
...如果有祈使体,海事组织最好使用doseq而不是map:
(doseq [name (client-names "Baltimore")]
(println name))https://stackoverflow.com/questions/15573378
复制相似问题