1

Let's say that I have the following :

(defn my-fn [params]
  (make-things (a-fn [ctx]
                 (do-this params)))

Now I wish to split this into different files, such that a-fn is in another namespace :

(defn my-fn [params]
  (make-things my.ns/a-fn))

But the problem now is that the params doesn't close over my function anymore. How should do that ?

nha
  • 17,623
  • 13
  • 87
  • 133

3 Answers3

2

Rewrite:

(defn my-fn [params]
  (make-things (fn a-fn [ctx]
                 (do-this params)))

into

(defn my-fn [params]
  (make-things ((fn a-fn-o [p]
                 (fn a-fn [ctx]
                   (do-this p)))
                params)))

This is what the compiler does for you when you close over variables.

Then it should be clear what to do in your other file. The function returns a function and you pass in params:

(defn my-fn [params]
  (make-things (my.ns/a-fn params)))

;; my.ns
(defn a-fn [params]
  (fn [ctx] (do-this params)))

Btw, your ctx parameter is unused.

ClojureMostly
  • 4,652
  • 2
  • 22
  • 24
1

Just so that's mentioned too, you might instead of closures also want to consider using a Var to scope the params dynamically rather than lexically. This is especially useful if they're "implicit arguments" to several related functions in my.ns.

(ns my.ns)

(def ^:dynamic *params* ...) ;;Optional default value here

(defn a-fn [...]
   (do-this *params* ...))

and then in the calling ns

(defn my-fn [params]
  (binding [my.ns/*params* params]
    (my.ns/a-fn ...)))

This is how for instance with-out-str alters the behaviour of any print variant both in its body and in subcomputations - by rebinding *out* to an empty string writer.

Magos
  • 3,004
  • 1
  • 20
  • 20
0

You could also use partial:

(ns my.ns)

(defn a-fn [params ctx]
  (do-this params))

Then in the calling context:

(defn my-fn [params]
   (make-things (partial my.ns/a-fn params)))
slipset
  • 2,960
  • 2
  • 21
  • 17