0
votes

I do not know if my title is clear but I would like to use a function which loads a file using namespaces aliases without requiring all libarires in every namespace of the stack. To make it clearer, here is a fake code :

My file to load ("whatever.clj") :

{:my-fn (fn [a b] (ml/explode a b))}

The namespace where the reader is defined :

(ns my-project.reader
  (:require [my-lib.core :as ml]))

(defn load-definition-and-apply
  [a b]
  (let [{:keys [my-fn]} (load-file "whatever.clj")]
    (my-fn a b)))

So if I run load-definition-an-apply from my-project.reader, it will work since ml/explode is defined. But now imagine that I use load-definition-and-apply from elsewhere :

(ns my-project.processing
  (:require [my-project.reader :as rd]))

(rd/load-definition-and-apply 1 2)

Will not work because ml alias is not found from my-project.processing during load-file. This is the same when I wrap the code around other process.
The solution is to do :

(ns my-project.processing
  (:require [my-lib.core :as ml]
            [my-project.reader :as rd]))

(rd/load-definition-and-apply 1 2)

Which is ok for one library but I actually imported several. Is there a clean way to do not import in every namespace of the tower the required libraries to read files and just call it for the namespace where the load-file is really conceptually "performed" (here : my-project.reader) ?

I do not want to put in on the clj files to load too because it is designed to be simple for the user.

Thanks

2
Look at binding or in-ns or along those lines. I've done it and if no-one answers I will, just don't have time right now. - Frank C.
Thanks, I used binding as you suggested and it worked ! - Joseph Yourine

2 Answers

1
votes

As Frank C. stated

(ns my-project.processing
  (:require [my-project.reader :as rd]))

(binding [*ns* (the-ns 'my-project.reader)]
  (rd/load-definition-and-apply 1 2))
1
votes

I think you have already answered your question. The idea is to use load-file function that loads a clojure file into the current namespace.

As I see, there is no a sense to have maps inside that file. Just put there (def ...) and (defn ...) forms, and that is it. If you aware of any possible naming conflict, prepend all the definitions with some prefix.

I think it is worth saying this way of load code on the fly is quite unobvious an difficult to maintain, debug, etc. It would be better to have just ordinary files with namespaces.

If it's a question of reusing your code, just publish it as a standalone library.