Clojure 只编写一个将给定对象保存到sqlite的函数
我只是从clojure开始,一直在思考如何实现看似简单的功能 有一个函数Clojure 只编写一个将给定对象保存到sqlite的函数,clojure,Clojure,我只是从clojure开始,一直在思考如何实现看似简单的功能 有一个函数generator,它将saver函数作为参数。generator执行各种操作并定期生成某些需要保存的数据对象。这个保存应该由saver函数来处理,因此生成器在每次生成数据时都会调用saver,其中包含需要保存的数据 现在,我要编写的一个保存函数是将数据保存到sqlite db的。我该怎么做 我想到的一个策略是在saver函数中创建到sqlite db的连接。每次保存数据时创建一个新连接,保存数据(一个表中只有一行)并关闭
generator
,它将saver
函数作为参数。generator
执行各种操作并定期生成某些需要保存的数据对象。这个保存应该由saver
函数来处理,因此生成器
在每次生成数据时都会调用saver
,其中包含需要保存的数据
现在,我要编写的一个保存函数是将数据保存到sqlite db的。我该怎么做
- 我想到的一个策略是在
函数中创建到sqlite db的连接。每次保存数据时创建一个新连接,保存数据(一个表中只有一行)并关闭连接。这似乎有点低效。特别是考虑到数据每2-5秒生成一次saver
- 另一个想法是作为模块级变量保持开放连接,在开始时设置为
。第一次调用nil
函数时会打开连接,并在后续调用中重复使用。这似乎更有效,但据我所知,它需要saver
函数中的saver
表单。就我个人而言,我不喜欢这样做def
- 还有一个(疯狂的?)想法是使用代理保存连接对象,最初设置为
。nil
将是一个向代理发送saver
数据的函数。代理,在第一次需要时创建连接,并保存在关联的数据对象中。这看起来可能很有效,但代理不是为此而设计的,是吗
另外,我花了很多时间写这篇文章,因为很难用语言表达我的问题。我不确定我是否弄对了。如果有不清楚的地方,请告诉我。您的第二个解决方案听起来最好。如果您不想使用可变的
Var
(通过def
创建),那么您可以在“工厂”函数中创建连接,作为一个简单的不可变值(因此它只是在闭包中携带):
免责声明:我不是伟大的clojure专家-以上是我在几乎任何函数式语言中都会这样做的。因此,也许有一种更为惯用的clojure方法。您知道如何关闭连接吗?或者这不重要——它可以继续出现吗?现在对我来说,这并不重要,但我愿意相信,当我的应用程序关闭时,jvm会优雅地关闭它。此外,在应用程序的整个生命周期中,我都需要连接。我认为在函数中使用def表单无法解决您的问题。def表单定义了一个不可变的绑定,而不管def是在哪里定义的。您不能使用def来表示“如果此值为null,请将其设置为非null,否则使用当前值。”据我所知,没有不可变绑定。您可以任意多次
def
和重新def
变量,尽管不鼓励这样做。绑定到变量的东西不是不可变的,创建的对象本身是不可变的。另外,def
表单在函数内部工作。当然,我希望clojure有更好的人来证实我所说的:)闭包。我怎么没想到呢!这太棒了。这正是我需要的解决方案。但正如你所说的,我愿意看到一个clojure式的方法,如果不同的话+1.如果没有人击败我,我会建议关闭。虽然使用代理序列化您的写入可能是一件好事,但如果您不介意让它们发生在后台,那么结合起来可能会更好。是的,我同意它发生在后台。但是代理的这个用例
不涉及代理的数据对象的任何突变。所以,我觉得代理对我想要实现的目标来说是太过了。然而,我喜欢让它在幕后发生的前景。比如(.start(Thread.saver fn))
,或者有更好的方法吗?
(defn sqlite-saver-factory [path]
(let [db-connection (open-sqlite-connection path)]
(fn [data]
(save-to-sqlite db-connection data))))
...
(generator (sqlite-saver-factory path) ...)