If you're working with multiple Clojure source files as a single project, you'll get a lot of mileage out of using a build tool like Leiningen or Boot. For example, here's how you could create a simple Boot project called myproject
with multiple source files.
First, create a myproject
directory (it doesn't matter where) with these contents:
myproject
├── build.boot
└── src
└── myproject
├── bar.clj
└── foo.clj
Boot will run your build.boot
file before it does anything else (e.g. running some of your code, creating a JAR, or starting a REPL). For now, all you need to tell Boot is that your source files will be in the src
directory, so just add this line to build.boot
:
(set-env! :source-paths #{"src"})
In bar.clj
, put the definition that you want to access from your other code:
(ns myproject.bar)
(def base-13-joke 42)
Then, in foo.clj
, you can reference bar.clj
using a :require
clause in your ns
declaration:
(ns myproject.foo
(:require [myproject.bar :as bar]))
(defn make-joke []
(println (Long/toString bar/base-13-joke 13)))
And that's all there is to it! Of course, you probably want to actually do stuff with the code you've just written. Boot handles "doing things" through tasks. Let's write one that simply runs one of the functions in your project.
When you want to define a task to run with Boot, you can do so by adding the code to define that task to your build.boot
file. First, though, since we're going to be calling some of our main code (in this case, the make-joke
function in the myproject.foo
namespace), we'll need to require
that code. Add this line to build.boot
:
(require '[myproject.foo :as foo])
Now we can define a simple run
task (again, in build.boot
) that will run our function:
(deftask run []
(with-pass-thru _
(foo/make-joke)))
The with-pass-thru
business just has to do with some of the specifics of tasks in Boot, which you can read about in detail here.
Executing tasks is quite easy. Run this in the command line from your project root:
$ boot run
33
Boot also comes with some tasks built-in. For instance, if you run boot repl
, you'll be presented with a familiar REPL prompt in the boot.user
namespace:
boot.user=>
This namespace is the same one in which Boot executes the build.boot
script, so since we have a require
for myproject.foo
in build.boot
, we can use that namespace in the REPL:
boot.user=> (foo/make-joke)
33
nil
Of course, you can require
other namespaces too:
boot.user=> (require '[myproject.bar :as bar])
nil
boot.user=> bar/base-13-joke
42
There's a whole lot more that you can do with Boot, like code reloading and interacting with CIDER, which you can read all about in the Boot Wiki.