0

I'm currently implementing multiple types with the same protocol as the basis and would like to reduce the number of files one would need to include in the namespace in order to use them. To give an example:

basetype.clj

(defprotocol Base
  (do-something [obj]))

(deftype Basetype [obj]
  ...
  Base
   (do-something [obj] something-something))

second_type.clj

(ns project.second-type
  (:use project.basetype))

(deftype DifferentType [obj]
  ...
  Base
   (do-something [obj] something-slightly-different))

What I did achieve is that everything built for Basetype also works with DifferentType. However, I'd like to access the function do-something simply by including second_type.clj in a namespace instead of including both. Is there a way to achieve this?

2
  • you can do the following to reexport do-something from second_type: at the end of seond_type.clj you (ns-unmap 'project.second-type 'do-something) and then (intern 'project.second-type 'do-something a/do-something) . then this do-something would be inmorted to anither namespace that requires second-type Commented Sep 16, 2020 at 16:08
  • 1
    Clojure deplores even the appearance of implementation inheritance: consumers operate on protocols and have no interest in the concrete type. They require basetype and call the plain-old-functions that defprotocol made in the basetype ns. There is another theory, that that's all nonsense; callers should use the Java interop dot notation (.methodName obj), so they do not require the basetype ns. But that's risky - you've ditched FP for OO and lost the opportunity to wrap defprotocol-created fns with your own fns that do more logging or type checking. Commented Sep 16, 2020 at 16:10

1 Answer 1

1

as i mentioned in my comment, you should be able to reexport any values from any namespace.

you could make up simple function like this:

(defn reexport [from-ns name]
  (ns-unmap *ns* name)
  (intern *ns* name @(ns-resolve from-ns name)))

(reexport 'project.basetype 'do-something)

or to reexport all the values from the given ns:

(defn reexport-all [from-ns]
  (run! (partial reexport from-ns) (map first (ns-publics from-ns))))

(reexport-all 'project.basetype)

in repl:

user> (ns x)
nil

x> (defn f [v] (inc v))
#'x/f

x> (ns y)
nil

y> (user/reexport 'x 'f)
#'y/f

y> (in-ns 'user)
#namespace[user]

user> (y/f 10)
11

user> (in-ns 'y)
#namespace[y]

y> (defn f2 [v] (dec v))
#'y/f2

y> (ns z)
nil

z> (user/reexport-all 'y)
nil

z> (in-ns 'user)
#namespace[user]

user> (z/f 1)
2

user> (z/f2 1)
0
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.