4

I know how to forward declare a var for the current namespace. Instead, I want to declare a var from another namespace. How do I do this? This will help me eliminate a circular load dependency.

At the moment, this is what I've tried:

; this_ns.clj
(ns my-project.this-ns
  (:require ...))
(ns my-project.other-ns)
(declare other-func)
(ns my-project.this-ns) ; return to original namespace
(defn func-1
  []
  (my-project.other-ns/other-func))

It works, but I don't like it.

David J.
  • 31,569
  • 22
  • 122
  • 174

1 Answers1

3

I think the solution you already have is the easiest one. If you wrap it into a macro it doesn't even look that bad anymore:

(defmacro declare-extern
  [& syms]
  (let [n (ns-name *ns*)]
     `(do 
        ~@(for [s syms]
            `(do 
               (ns ~(symbol (namespace s)))
               (declare ~(symbol (name s)))))
        (in-ns '~n))))

Call it with:

(declare-extern my.extern.ns/abc) ;; => #<Namespace ...>
my.extern.ns/abc                  ;; => #<Unbound Unbound: #'my.extern.ns/abc>
xsc
  • 5,983
  • 23
  • 30
  • 2
    But addressing (+ eliminating) the dependency circle would probably a better approach to your problem, making things easier in regard to future changes to your code. – xsc Nov 18 '13 at 17:38
  • Is "unbound" what you expected? That behavior is consistent with what I'm seeing based on my interpretation of David James' suggestion. How is it supposed to work? – Mars May 17 '15 at 03:54