Clojure的-main函数没有完全执行

时间:2015-02-13 11:52:22

标签: clojure

这是预期的行为,还是我的Clojure安装问题(我在Windows和Linux上检查它)?

我有一个简单的项目,使用lein new app testfor创建。这是src/testfor/core.clj的代码:

(ns testfor.core
    (:gen-class))

(defn -main [& args]
    (println "hello")
    (for [x [1 2 3]]
        (println x)))

当我从REPL运行lein repl并调用(-main)时,输出为:

testfor.core=> (-main)
hello
1
2
3

然后我用lein runlein uberjar运行应用程序并运行生成的JAR文件,输出为:

$ lein run
hello

因此,它以某种方式不运行for循环。

我在这里做错了吗?

2 个答案:

答案 0 :(得分:5)

我相信这是因为for会返回一个懒惰的元素序列 - https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/for

在从repl调用-main函数的示例中,在这种情况下,函数中的最后一个表达式从函数调用返回(就像任何其他函数调用一样)。 REPL看到lazy-seq并尝试打印它,这需要实现seq,它将评估println语句。

在Leiningen调用main方法的示例中,它类似于在具有void返回类型public static void main的Java类上调用main方法。 Clojure会将其视为懒惰,并且没有尝试实现seq,因此永远不会评估println表达式。

答案 1 :(得分:3)

for不像Java那样是for循环。它会创建一个延迟序列,该序列取决于您指定的不同选项。请参阅for文档。

您的案例中的重点是 lazy 字。 repl实际上会强制实现延迟序列,但是当使用lein运行时,情况并非如此。为了做你想做的事,你需要强制使用dorundoall

(defn -main [& args]
  (println "hello")
  (dorun (for [x [1 2 3]]
           (println x))))


cuvier:tgo$ lein run
hello
1
2
3