我该如何运行我创建的.clj Clojure文件?

85

我在Linux上写了一个小的“hello world”程序,以便开始使用这种语言。

现在我想运行它并查看输出结果。

我应该如何运行这段代码? 我应该运行哪个命令?

10个回答

90

就我理解,这个问题特别是询问如何运行单个文件,比如脚本,而不是作为编译项目的一部分。

当然,运行单个文件与构建完整项目之间有关联,因此我也会考虑一些相关因素。

最佳选择:使用clj工具

文档在这里:

https://clojure.org/guides/deps_and_cli

这是Clojure项目的官方部分,这本身就是一个非常好的理由。但是,它比其他解决方案具有几个优点:

  • 通过deps.edn更清晰的依赖项解析模型
  • 还可以通过git引用解决依赖项!
  • ~/.clojure/deps.edn似乎比~/.lein/profiles.clj更好地通过其别名提供可重用功能
  • 如果需要在repl中加载代码,则像lein repl一样,clj不会在破损的src文件上卡住

简单地说,

clj your-code-file.clj

如果你有依赖项

clj -Sdeps '{:deps {clj-time {:mvn/version "0.14.2"}}}' -M your-code-file.clj

在脚本中作为shebang工作得很好!

#!clj -Sdeps '{:deps {clj-time {:mvn/version "0.14.2"}}} -M
(ns my-crazy-script!
  (:require ...))
...

我建议使用homebrew进行安装,它现在适用于Mac和Linux。如果您使用的是Windows,则建议使用WSL+brew。

我认为lein(见下文)工具通常比clj工具更具优势的一点是,在达到那个点时,lein处理了代码库的一些构建打包过程。 但是,还有其他处理这些问题的方式(请参见packuberdeps或cambada),并且上面提到的clj的优点在我的意见中超过了其不足之处。

Babashka

如果您尝试运行单个文件而不是整个项目,则很可能位于“脚本编写”领域。 不幸的是,JVM需要一段时间来启动,Clojure本身也是如此。 通过GraalVM的魔力和SCIBabashka能够以惊人的快速启动时间支持大多数Clojure语言。它还带有许多适用于典型脚本任务的“内置电池”,使其成为在需要快速执行、短期生命周期进程时与clj完美搭配的工具。

安装后,您可以简单地运行bb your-code-file.clj,或在您的shebang中使用#!bb。 有关更多使用说明,请参阅文档:

https://babashka.org/

使用leinlein-exec

如果您喜欢lein工具,或者已经有一个~/.lein/profiles.clj文件可用,并且不想投资学习clj/deps.edn,您可以考虑查看lein-exec

如果您已经设置了依赖项的project.clj,那么您当然可以运行lein run -m <yer-namespace>[/<yer-main-fn>]

如上所述,lein的优点之一是它是一个完整的构建工具,并且可以使用lein jarlein uberjar为您创建jar / uberjar,进行部署等。

适用于ClojureScript

我建议使用http://planck-repl.org/。它现在支持(引导)快速启动ClojureScript脚本,无需启动JVM或Clojure。 与babashka一样,这使它非常适合脚本编写。然而,我发现babashka更强大、更自然地进行脚本编写,因此除非您有特定的原因想要使用Cljs(更熟悉JS/node,需要某些cljs库等),否则我会从babashka开始。

java -cp clojure.jar clojure.main file.clj

但是在实际使用中,你很少看到这种情况,因为找到clojure.jar的路径并手动组合依赖项的类路径是一件麻烦的事情。

不过,你知道,每个人都有自己的选择。


1
谢谢!请执行命令 sudo apt-get install clojure,然后运行 clojure hello.clj - CornSmith
2
lein exec 是正确的方式。 - qed
如果你正在寻找如何安装exec插件的方法,我写了一篇快速而简单的博客文章。链接在这里:https://quazirfan.wordpress.com/2017/06/13/installing-exec-plugin-in-leiningen-project/ - Quazi Irfan
3
为什么要使用 lein exec 而不是 clojure 呢?@qed - Alexander Presber
我得到了Exception in thread "main" java.io.FileNotFoundException: <FILE>.clj (No such file or directory) - Snehaa Ganesan
显示剩余7条评论

59
你可以使用以下命令运行脚本:

java -cp clojure.jar clojure.main file.clj

但更好的做法是使用leiningen,特别是当您开始向项目添加依赖项时。Lein提供了许多命令来运行您的代码(包括所有必要的依赖项),使用lein jar将代码打包成存档文件,或创建完整的、独立的存档文件使用lein uberjar,您可以通过以下方式运行它们:

java -jar your_app.jar

命令

P.S. 你可以阅读下面的文章了解如何使用lein——它描述了基本任务和配置。


1
也许需要补充说明他必须首先使用lein new创建一个项目,并将clj文件作为项目的一部分,例如core.clj。 - Michiel Borkent
是的,创建项目可能很有用……我已经在我的文章中添加了如何使用lein的链接。 - Alex Ott
Alex,我一直在尝试这个,但它只显示一个空行;我在文件中有一个println,但它从未打印出来;我错过了什么吗? java -cp clojure-1.6.0.jar clojure.main ..\hey.clj - Gans
对我来说很好用...你的源代码中顶层有println吗,还是在函数内部?如果是后者,则该函数已编译但从未运行...以下内容对我而言没有任何问题:echo '(println "test")' > 1.clj ; java -cp ~/.m2/repository/org/clojure/clojure/1.6.0/clojure-1.6.0.jar clojure.main 1.clj - Alex Ott
我一直收到 Exception in thread "main" java.io.FileNotFoundException: <FILENAME>.clj (No such file or directory) 的错误信息。 - Snehaa Ganesan

16

一旦你安装了 lein 和 lein-exec 插件,运行你创建的 .clj 文件就像这样简单:

lein exec hello.clj

如果您正在传递命令行参数,例如

lein exec hello.clj arg1 arg2 arg3

你可以在hello.clj的'foo'函数中访问它们,如下所示:

(foo *command-line-args*) 

9

对于单个clj文件,您可以添加以下内容:

#!/usr/bin/env java -cp /path/to/clojure-1.2.0.jar clojure.main

您可以将文件移动到顶部并使其可执行,或者使用Leiningen,它是一个Clojure构建工具,它会创建一个包含所有内容的单个JAR文件,然后您只需执行以下操作:

java -jar cool_app.jar

2
如果你只想执行单个文件,可以尝试通过管道将其输入repl中,例如: cat $PATH_TO_FILE | lein repl

2

使用以下命令通过命令行运行单个文件:

clj -m (NameSpace name)

例如:clj -m Sample

或者如果您想通过repl运行:

(load-file filelocation)

ex:

 (load-file "Sample.clj")

1

我非常喜欢编写小的.clj脚本,但有时这些脚本需要安装依赖项。由于其他答案都没有涵盖这种情况,因此在这里提供一个示例。这个示例是一个单文件脚本,需要从math.combinatorics库中调用permutations函数。


繁琐的仅限于Mac的解决方案

#!/usr/bin/env clj -Sdeps {:deps,{org.clojure/math.combinatorics,{:mvn/version,"0.1.6"}}} -M
; Explanation for the shebang:
;   -Sdeps  Specify deps in EDN format
;   ,       Clojure interprets commas as whitespace. Without the commas, the EDN is
;           broken up into multiple arguments and the command fails. On the
;           command line you can use single quotes around the EDN string, but
;           Mac shebangs don't support quoting around arguments.
;   -M      Run the program as a "main" function

(ns foo
  (:use [clojure.math.combinatorics :only (permutations)]))

(dorun (map #(println (apply str %)) (permutations "abcde")))

仅适用于Linux的解决方案

#!/usr/bin/env -S clj -Sdeps '{:deps {org.clojure/math.combinatorics {:mvn/version "0.1.6"}}}' -M
; Explanation for the shebang:
;   env -S  Allow multiple arguments to be passed to the following command
;   -Sdeps  Specify deps in EDN format
;   -M      Run the program as a "main" function

(ns foo
  (:use [clojure.math.combinatorics :only (permutations)]))

(dorun (map #(println (apply str %)) (permutations "abcde")))

便携式解决方案(适用于Linux和Mac)

请参考planck文档获取详细说明。它非常巧妙!

#!/usr/bin/env bash
"exec" "clj" "-Sdeps" "{:deps {org.clojure/math.combinatorics {:mvn/version \"0.1.6\"}}}" "-M" "$0" "$@"

(ns foo
  (:use [clojure.math.combinatorics :only (permutations)]))

(dorun (map #(println (apply str %)) (permutations "abcde")))

1

Drip 可能现在是这个问题的最佳答案(有关使用Drip与Clojure的详细信息,请参见Drip's wiki)。

Cake已被纳入Leiningen,自那以后已被Drip取代作为Clojure自动化的最稳定实现 - 在此处查看类似问题的答案


0

我在使用lein命令时遇到了类似的问题,无法运行Clojure项目中的特定脚本文件。后来我找到了一个快捷方式,并想分享给大家。

project.clj文件中,你可以切换Clojure脚本文件的名称(当然必须包含主方法)。以下是实现这一功能的语句:

:main ^:skip-aot conv.newconv ; 这里的conv是命名空间,newconv是文件名 .

注意:我对Clojure还不熟悉,不确定为什么要使用'^:skip-aot',我还没有去查看。

注意:这种方法不需要安装任何插件,也不需要生成任何JAR文件。只需在项目文件中更改一个名称即可。

假设:你的Clojure项目中有多个Clojure文件,每个文件都有主方法。我假设这些文件只是为了测试目的而创建的。我的解决方案适用于这种特定情况。


0

根据您的操作系统从以下官方链接安装Clojure

https://clojure.org/guides/install_clojure

现在我们可以通过以下命令轻松执行文件,仅限于Mac测试。现在不再需要其他复杂的步骤了。

在您的文件hello-world.clj中编写一个示例打印语句。

(println "Hello world") 

在终端中使用以下命令运行您的程序:
clj -M hello-world.clj

它将输出

Hello world

在Clojure 版本:1.11.1.1200上进行了测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接