The beauty of Clojure's non-OOP style is that the functions are not tied to some blueprint that needs to be instantiated. Instead, once they are included, required, or loaded, etc. the functions are just there, able to be called at some later point in the code. Because of this, Idiomatic Clojure lends itself well to functions that are pure and can be called in complete isolation. It should be noted that load-file works for both Clojure and ClojureScript!
In the world of Clojure, REPLs are everything. Luckily, there are lots of REPLS to choose from such as nREPL in Leiningen or Boot for good ole' JVM Clojure and Leiningen, Lumo, Plank, or Klipse for ClojureScript. This isn't a guide on setting up a REPL, but just know that load-file should work for any REPL, on both Clojure and Clojurescript!
Loading A Source File
Suppose you have typed a single function into a Clojure or ClojureScript file (with a clj or cljs file extension, respectively). I'm going to save the snippet below as derp.cljs and use lumo, but you could just as well do this with a cljs file and leiningen.
All this code does is defin a function named derpy that, when called, returns the number 42. Now, let's look at calling it. I'll boot up lumo by typing the simple lumo command into my shell.
Alright then. Now that your REPL is started, it's time to get down to the magical goodness of load-file!
It's a big worrying if you're used to instant feedback. load-file is the kind of thing where it just gives you an empty prompt if it worked, or some type of "Could not load file" error if it didn't. Now that we've loaded the file containing our functions, let's call them!
Huzzah!! For today is a glorious day because we are able to use a REPL to evaluate Clojure functions! But wait... there's more!
Load Files In Different Folders
Now let's say that you want to load a file from some random directory. Welp, you can just enter the path to the file in the string that you provide to load-file. Note that the path is relative to the directory you were in when you started the REPL.
Load-File With Namespaces
In a "real life" Clojure or ClojureScript project you won't often see files with loose functions defined in them like the files here. For the most part each file has a namespace declared at the top of the file, and this makes the fuctions scoped to that namespace. This is important because you just call the functions like this anymore when you load the file. Instead, you need to either :refer certain functions or explicitly use a library alias when calling the functions. To demonstrate what I might let;s look at an example. Let's create a new file and named and write in it the snippet of code below.
Now back in our RELP we can load the nampespace, but we can
t just call straight up (derpstring).
The above code gives us that error, but we CAN call derpstring with the code below.
Ah yes, there's our cute little derp string. Although this works, it's quite annoying to have to write out this huge namespace every time you want to call a function. I mean good golly, such finger energy wasted! It should be a crime! One thing we can do is cal l"in-ns" which allows us to call functions from that namespace without writing out the full path.
Another thing we can do is alias the namespace so that we can give it a shorter name. Note: alias is onoly a function in JVM Clojure, not ClojureScript.
Yep, load-file is a great tool to keep in your trusty Clojure knapsack, but now let's take a look at require!
Using Require From The REPL
You will probably see require more often that load-file, to be honest. This is because require (or with a namespace declaration, :require) is a function that you can use in a project with multiple files whereas load-file is strictly meant to be called at a REPL. Let's take a look at how we can use require with our cute little ClojureScript file. We'll first go back to the no-namespace derp.cljs file from the beginning of this post. If you want to use require to load a file that has no namespace, don't fret; you can do it! Just navigate into the folder that contains the file, load up your repl, and call require on the name of your file (no string quotes, just a single quote in front).
Please note that only ClojureScript will allow you to require a file with no namespace. JVM Clojure should throw an error.
Alright, so what if we DO have a namespace in our file. What do we do then? Well, we simply require the namespace and the Clojure compiler will find the file on its own! Well, it's not really finding the file on its own; you're telling it how to find it! You see, when you use require the namespace must match the path to the file. If you use "." in the namespace this signifies drilling down into a folder. In the example below, you must name the file "gg.cljs" or "gg.clj" for it to work!
Now let's suppose you create a folder named "root" and one inside of it called "derpskies". You place this file, gg.cls, inside of the derpskies folder and in your command shell navigate into the root folder. Let's change our file to reflect this new namespace.
With this we can require and call the functions like so:
That works, but it's rather wordy. Let's give an alias to our library with the :as macro.
This above snippet shows about how to call a function from a nice, short alias. How lovely. But it get's even better! Suppose you have a big old file with loads of functions, but you only need one? Well, you can import just these functions and tell Clojure that you are referring to the functions from that specific file or library.
REPL Driven Development
The posts on this site are written and maintained by Jim Lynch. About Jim...