83

I wrote a small "hello world" program on Linux to get started with the language.

Now I'd like to run it and see what it outputs.

How can I run this code? What command should I run?

Kevin Languasco
  • 2,318
  • 1
  • 14
  • 20
Only Bolivian Here
  • 35,719
  • 63
  • 161
  • 257

10 Answers10

87

FWIW, I'm interpreting the question here as specifically asking how to run a single file, like a script, versus as a part of a compiled project. Obviously though, there's a relationship between how and why you would want to run a single file, and how you would want to build a full project, so I weigh that in some as well.

Best choice: the clj tooling

Docs are here:

https://clojure.org/guides/deps_and_cli

This is an official part of the Clojure project, which by itself is a pretty good reason to go this route. However, it has a couple of advantages over the other solutions here:

  • cleaner dependency resolution model, via deps.edn
  • also resolve dependencies via git references!
  • ~/.clojure/deps.edn seems to do a better job of cleanly providing reusable functionality via its aliass than ~/.lein/profiles.clj
  • if you need to load your code in a repl, clj won't choke on a borked src file, like lein repl does

Simply

clj your-code-file.clj

Or if you have dependencies

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

Works well as a shebang in scripts as well!

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

I recommend installing with homebrew, which now works on both Mac and Linux. If you're on Windows I'd recommend using the WSL+brew.

The one advantage I see of lein (see below) tooling over clj generally is that lein handles a little more of the process of building and packaging your code base, when you get to that point. However, there are other ways of handing that (see pack, uberdeps or cambada), and the advantages of clj mentioned above outweigh IMHO.

Babashka

If you are trying to run a single file, as apposed to an entire project, there's a good chance your in "scripting territory". Unfortunately, the JVM takes a while to boot up, as does Clojure itself. Via the magic of GraalVM and the SCI, Babashka is able to support most of the Clojure language with blazing fast startup times. It also comes with quite a few "batteries included" for typical scripting tasks, making it a perfect complement to clj when you want fast-executing, short lived processes.

Once you install it you can simply bb you-code-file.clj, or use #!bb in your shebang. See the docs for more usage instructions:

https://babashka.org/

With lein & lein-exec

If you prefer lein tooling, or have a ~/.lein/profiles.clj file handy already and don't want to invest in learning clj/deps.edn, you can consider looking at lein-exec.

If you already have a project.clj set up with dependencies, you can of course run lein run -m <yer-namespace>[/<yer-main-fn>].

As mentioned above, the one advantage of lein over clj is that it is a complete build tool, and can make jars/uberjars for you with lein jar or lein uberjar, do deploys and such.

For ClojureScript

I'd recommend http://planck-repl.org/. It now supports (bootstrapped) quick launching of ClojureScript scripts without having to fire up the JVM or Clojure. Like babashka, this makes it great for scripting. However, I find babashka both more powerful and more natural for scripting, so I'd start there unless you have a particular reason for wanting to use Cljs (more familiarity with JS/node, need of certain cljs libraries, etc).

For more substantial projects (beyond scripting), you may want to look at Shadlow-CLJS, for its ease of incorporating vanilla JS projects. And FWIW, Shadow nicely integrates with both deps and lein, and has it's own built in hode code reloading, like figwheel.

With java

You can, of course, as has been suggested in another answer, use

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

But you don't see that in the wild too often, because it's a pain to have to find the path to your clojure.jar and manually composing classpaths for dependencies sucks. But, you know, to each their own.

metasoarous
  • 2,854
  • 1
  • 23
  • 24
  • 1
    Thank you! `sudo apt-get install clojure` and then `clojure hello.clj` – CornSmith Dec 13 '14 at 22:32
  • 2
    lein exec is the way to go. – qed Jan 17 '15 at 00:52
  • @qed - Agreed; that's the way I typically go. – metasoarous Jan 18 '15 at 00:46
  • If you are looking for it, I wrote a quick and dirty [blog](https://quazirfan.wordpress.com/2017/06/13/installing-exec-plugin-in-leiningen-project/) post about how to install the exec plugin. – Quazi Irfan Jun 13 '17 at 22:06
  • 3
    @qed Why is `lein exec` "the way to go"? Why not use `clojure` ? – Alexander Presber Jan 08 '18 at 17:36
  • @AlexanderPresber Because `lein` gives you a way to declare dependencies, while `clojure` does not. – metasoarous May 06 '19 at 21:39
  • Note: I've updated the answer here to reflect that we now have the "official" `clj`/`clojure` CLI tools available. The `clojure` tooling here is not to be confused with the `clojure` I mentioned in an earlier version of this, which was put up on Ubuntu by who knows. Just for context for those of you reading comments above. – metasoarous Apr 11 '20 at 14:59
  • Another option for lein which I prefer over `lein-exec` is `inlein` https://github.com/hypirion/inlein – Didier A. Nov 05 '20 at 11:02
  • I am getting `Exception in thread "main" java.io.FileNotFoundException: .clj (No such file or directory)` – Snehaa Ganesan Nov 24 '20 at 16:25
  • Hi @SnehaaGanesan. A little hard to know what might be going on here without more details. Do you want to post your issue as a separate question? – metasoarous Nov 25 '20 at 23:19
  • Update : I was executing it from the wrong directory. Had to be in the root of the class path for a successful execution. Thank you @metasoarous for the suggestion. – Snehaa Ganesan Nov 30 '20 at 14:56
  • @metasoarous Your shebang answer did not work for me. I think `-deps` should be `-Sdeps`, the single-quote around the deps is never balanced, and newer `clj` versions will complain about "Implicit use of clojure.main" without the `-M` flag. I added an answer to cover the shebang-deps case for Linux and Mac: https://stackoverflow.com/a/72583270/2016618 – Sarkom Jun 11 '22 at 09:48
59

You can run script with following command:

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

but it's better to use leiningen, especially when you'll start to add dependencies to your project. lein provides number of commands to run your code (with all necessary dependencies), pack code into archive with lein jar, or create complete, independent archives with lein uberjar that you can run with:

java -jar your_app.jar

command

P.S. You can read how to use lein in following article - it describes base tasks & configurations

Alex Ott
  • 80,552
  • 8
  • 87
  • 132
  • 1
    Maybe add that he has to make a project first with lein new and make the clj file part of the project, for example core.clj – Michiel Borkent Oct 05 '11 at 06:52
  • Yes, it's creating project could be useful... I added link to my article on how to work with lein – Alex Ott Oct 05 '11 at 08:49
  • Alex, I have been trying this but it just shows an empty line; I have a println in the file but it never prints it; is there any thing am missing? java -cp clojure-1.6.0.jar clojure.main ..\hey.clj – Gans Dec 08 '14 at 12:45
  • Works fine for me... Do you have println in the top-level of the source code, or inside the function? If the later, then the function is compiled, but never run... Following works for me without any problem: `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 Dec 09 '14 at 19:27
  • I keep getting `Exception in thread "main" java.io.FileNotFoundException: .clj (No such file or directory)` – Snehaa Ganesan Nov 24 '20 at 16:23
16

Once you've installed lein and the lein-exec plugin, running the .clj file you've created is as simple as

lein exec hello.clj

In case you're passing command line arguments like

lein exec hello.clj arg1 arg2 arg3

you can access them in the 'foo' function in your hello.clj like

(foo *command-line-args*) 
Brad Koch
  • 19,267
  • 19
  • 110
  • 137
finiterecursion
  • 161
  • 1
  • 3
9

For a single clj file you can add,

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

to the top of the file and make it executable or you can use leiningen which is a clojure build tool it will create a single jar that has everything packed, then you can just do,

java -jar cool_app.jar
Hamza Yerlikaya
  • 49,047
  • 44
  • 147
  • 241
2

if you just want to execute a single file, how about piping it to the repl like:

cat $PATH_TO_FILE | lein repl

Will Munn
  • 7,363
  • 4
  • 27
  • 32
2

For running a single file through command line use the following commands:

clj -m (NameSpace name)

ex: clj -m Sample

Or if you want to run through repl:

(load-file filelocation)

ex:

 (load-file "Sample.clj")
petezurich
  • 9,280
  • 9
  • 43
  • 57
1

Drip is probably now the best answer to this question (see Drip's wiki for details on using Drip with Clojure).

Cake was incorporated into Leiningen and has since been superseded as the most stable implementation of Clojure automation by Drip - see this answer to a similar question here.

Community
  • 1
  • 1
duncsoz
  • 153
  • 1
  • 7
1

I really like writing small .clj scripts, but sometimes those scripts have dependencies that need to be installed. Since none of the other answers cover that case, I provide an example here. This example is a single-file script that requires the permutations function from the math.combinatorics library.


Cumbersome Mac-only solution

#!/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-only solution

#!/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")))

Portable solution (Linux and Mac)

See the planck docs for an explanation. It's very clever!

#!/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")))
Sarkom
  • 823
  • 10
  • 12
0

I had similar issue in running a specific clojure script file out of a clojure project using lein. Then I found a shortcut, thought of sharing the same.

In project.clj file, you can toggle the clojure script file name ( which has main method of course). Following is the statement for this.

:main ^:skip-aot conv.newconv ; here conv is namespace and newconv is the file name .

Note: I am new to clojure and I am not sure why '^:skip-aot` is used, I have not checked that.

Note: This methodology, does not require any plugin to be installed nor any jar file need to be generated. This only requires to change a name in project file.

Assumption: Your clojure project has multiple clojure files, each having main method. I am assuming this is created for testing purpose only. My solution will work for this specific scenario.

Arindam Nayak
  • 7,346
  • 4
  • 32
  • 48
0

Install clojure from the below official link according to your OS

https://clojure.org/guides/install_clojure

Now we can easily execute files by below command tested on mac only. Other complicated steps aren't required now I think.

write a sample print statement in your file hello-world.clj

(println "Hello world") 

Run your program with the below command in terminal

clj -M hello-world.clj

It will output

Hello world

Tested on Clojure Version: 1.11.1.1200

Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54