【问题标题】:Inconsistency running a clojure jar from command line从命令行运行 clojure jar 的不一致
【发布时间】:2011-12-04 11:49:46
【问题描述】:

我有一个 clojure 程序,它有时会执行一个名为 db-rebuild-files-table 的函数。 此函数将目录文件名作为单个字符串参数并调用递归函数,该函数下降到目录文件树中,从那里的文件中提取某些数据并将每个文件记录在 mysql 数据库中。此命令的最终结果是一个“文件”表,其中包含给定目录下树中的所有文件。

我需要的是能够从 shell 定期运行这个命令。

所以,我在包含我的-main 函数的文件中添加了:gen-class 指令,该函数实际上调用了(db-rebuild-files-table *dirname*)。我运行 lein uberjar 并生成一个 jar,然后我可以使用它来执行:

java -jar my-project-SNAPSHOT-1.0.0-standalone.jar namespace.containing.main

果然,函数运行了,但在数据库中只存在一个条目,用于目录 *dirname*。当我在 clojure REPL 中执行 exact same sexp 时,我得到了正确的行为: *dirname* 下的 all the file tree 得到处理。

我做错了什么?为什么调用 (db-rebuild-files-table *dirname*) 从 REPL 调用和从命令行执行时行为不一致?

[编辑] 更奇怪的是,我在任何地方都没有出错。所有函数调用似乎都可以正常工作。我什至可以在 REPL 中运行 -main 函数,它会正确更新表。

【问题讨论】:

  • 您使用的是哪个版本的 Clojure?

标签: jdbc clojure read-eval-print-loop


【解决方案1】:

如果这在 REPL 中有效,但在独立执行时无效,那么我猜你可能会被 Clojure 的懒惰所困扰。

您的代码是否可能需要 doseq 才能获得副作用(例如写入数据库)的好处?

【讨论】:

  • 没错。谢谢!在您发布此内容之前,我在上面写下了我的答案。 [编辑] 作为记录,我将按照你的建议使用 doseq 重写我的实现,因为文件树可能很大,不需要用 doall 将它全部保存到内存中。
【解决方案2】:

成功了。这是我的程序中的一个非常隐蔽的错误。我被clojure的懒惰咬了。 我的文件树函数在内部使用了 map,因此只生成了第一个值,即根目录。由于某种原因,我仍然无法弄清楚,当在 REPL 执行时,评估实际上是强制的,并且生成了整个树序列。我刚刚在我的函数中添加了一个doall 并解决了它。

仍然试图弄清楚为什么在 REPL 执行某些东西会强制评估。有什么想法吗?

【讨论】:

  • REPL 总是打印给它的最后一个表达式的返回值,因此它需要评估序列以便打印最后一个表达式作为输出。相反,对于“正常”运行的 Clojure 程序,情况并非如此。我一直被这个抓住(但它确实很有意义)!
猜你喜欢
  • 2011-06-04
  • 2020-12-24
  • 1970-01-01
  • 2021-04-08
  • 2016-10-10
  • 1970-01-01
  • 2014-08-24
相关资源
最近更新 更多