77

In Clojure and clojurescript you can have a private version of defn called defn-, but how do you do the same for def, as def- doesn't seem to be included?

yazz.com
  • 57,320
  • 66
  • 234
  • 385

5 Answers5

111

You have to add the :private true metadata key value pair.

(def ^{:private true} some-var :value)
;; or
(def ^:private some-var :value)

The second form is just a short-hand for the first one.

juan.facorro
  • 9,791
  • 2
  • 33
  • 41
19

It's worth mentioning, that currently it's not possible to have a private def (and defn) in ClojureScript: https://clojurescript.org/about/differences (under "special forms")

Compilation won't fail and but the def will stay accessible.

Mik
  • 4,117
  • 1
  • 25
  • 32
16

If you want a def-, here's how to implement it

(defmacro def- [item value]
  `(def ^{:private true} ~item ~value)
)
Tom Parker-Shemilt
  • 1,679
  • 15
  • 26
  • 8
    This does not actually work, see this thread for an explanation https://groups.google.com/forum/#!topic/clojure/O7xWh72zzuo . The proper macro is `(defmacro def- [sym init] \`(def ~(with-meta sym {:private true}) ~init))` – ark Oct 08 '16 at 19:47
  • 1
    @ark That's better but lacks support for the docstring. See [my answer](https://stackoverflow.com/a/50471316/1228933) for an implementation almost identical to `defn-`. – John May 24 '18 at 12:32
10

This google group post has a discussion about this topic. Apparently the request has been considered. According to one of the responses, defn- was deemed to not be a good idea and decided not to perpetuate it with def and others.

leeor
  • 17,041
  • 6
  • 34
  • 60
  • my take from the linked post is that `clojure.core` is not the place for `defn-`, not that `defn-` was not good at all. +1 for the link to the post, though – beluchin Jan 15 '19 at 09:07
9

Here's how to implement def-:

(defmacro def-
  "same as def, yielding non-public def"
  [name & decls]
  (list* `def (with-meta name (assoc (meta name) :private true)) decls))

This code is very similar to that of defn-, which you can look up using (clojure.repl/source defn-):

(defmacro defn-
  "same as defn, yielding non-public def"
  {:added "1.0"}
  [name & decls]
  (list* `defn (with-meta name (assoc (meta name) :private true)) decls))
John
  • 964
  • 8
  • 21