我花了一些时间研究这个,虽然我找到了一些相关的信息,
这是我发现的:
if __name__ == '__main__'
的等效内容是什么?”但他们都没有令人满意地回答这个问题。
我的Clojure源代码文件定义了命名空间和一堆函数。当源文件作为脚本运行时,我还希望调用一个函数,但是当它作为库导入时,从不。
所以:现在是2012年,有没有办法做到这一点,没有AOT编译?如果是的话,请赐教!
答案 0 :(得分:2)
我假设通过作为脚本运行你的意思是通过clojure.main,如下所示:
java -cp clojure.jar clojure.main /path/to/myscript.clj
如果是这样,那么有一种简单的技术:将所有库函数放在一个单独的命名空间中,如mylibrary.clj
。然后myscript.clj可以使用/ require这个库,你的其他代码也可以。但是myscript.clj中的特定函数只有在作为脚本运行时才会被调用。
作为奖励,这也为您提供了良好的项目结构,因为您不希望脚本特定的代码与您的常规库函数混合在一起。
编辑:
我不认为Clojure本身有一种强大的方法可以确定单个文件是作为脚本启动还是作为库加载 - 从Clojure的角度来看,之间没有区别两个(它们都以相同的方式通过Compiler加载。在Clojure源代码中加载(...)以供任何感兴趣的人使用。
选项,如果您真的想要检测启动的方式:
答案 1 :(得分:1)
我提出了一种方法,虽然存在严重缺陷,但似乎有效。
我确定程序作为脚本运行时已知哪些名称空间。然后我可以将该数字与运行时已知的命名空间数进行比较。我们的想法是,如果文件被用作lib,那么至少应该存在一个比脚本情况更多的命名空间。
当然,这非常黑客和脆弱,但似乎确实有效:
(defn running-as-script
"This is hacky and brittle but it seems to work. I’d love a better
way to do this; see http://stackoverflow.com/q/9027265"
[]
(let
[known-namespaces
#{"clojure.set"
"user"
"clojure.main"
"clj-time.format"
"clojure.core"
"rollup"
"clj-time.core"
"clojure.java.io"
"clojure.string"
"clojure.core.protocols"}]
(= (count (all-ns)) (count known-namespaces))))
答案 2 :(得分:1)
这可能会有所帮助:github项目lein-oneoff将自己描述为“对一次性单文件clojure程序的依赖管理。”
这允许您在一个文件中定义所有内容,但是您需要安装oneoff
插件才能从命令行运行它。