If you’ve been programming in Clojure for longer than, oh, about 5
minutes, you probably already know how
defn creates a publicly
accessible function in a namespace, while
defn- creates a private
one. If you’re outside the original namespace and you try to call a
private function, you will get the smackdown.
Here’s a simple demonstration. We’ll create two functions, one public
and one private, in the
user> (defn hello  "Hello World") #'user/hello user> (hello) "Hello World" user> (defn- secret  "TOP SECRET") #'user/secret user> (secret) "TOP SECRET"
If we switch to the
other namespace, though, we can only use the
user> (ns other) nil other> (user/hello) "Hello World" other> (user/secret)
var: #'user/secret is not public [Thrown class java.lang.IllegalStateException]
However, you can get around the private flag; all you need to do is refer directly to the function’s var:
other> (#'user/secret) "TOP SECRET"
You can make it a bit easier by creating a var in your new namespace that points to the private one:
other> (def secret #'user/secret) #'other/secret other> (secret) "TOP SECRET"
Now why the hell would you ever want to do this? In general, you probably shouldn’t, at least with other people’s code. Private functions are private for a reason; they’re not part of any public API, so they could disappear or change at a moment’s notice. However, it can come in handy when you’re testing your own code. Often, I’ll have a few private functions that do something useful within a namespace, but really have no business being used anywhere else. Sometimes when I’m testing my public functions, though, I’ll find myself needing these private functions to either set things up, create test data, or otherwise verify that things turned out alright.
You could also create a separate namespace for all your private helper functions (making them public this time), and then only ever pull that namespace into your main and test namespaces (Fogus and Chouser describe this approach in Section 9.1.2 of The Joy of Clojure; conveniently this chapter is also available as a free download). If you’ve only got a handful of these functions, though, this var shadowing trick is pretty straightforward.