Clojure: Expand a var in let binding

2019-07-16 03:42发布

问题:

I want to reuse a set of local assignments in the let form of different functions. Let's say

(def common-assign
  [x 10
   y 20])

one way to do it is with eval:

(eval `(defn ~'foo []
         (let [~@common-assign
               ~'hello "world"])
         balala))

The problem is that now you have to quote all other symbols, which is cumbersome.

Is there any other clean way to do what I want?

回答1:

(defmacro with-common [& body]
  `(let ~'[x 10, y 20]
     ~@body))

(with-common (+ x y))


回答2:

(def common-assign
  ['x 10
   'y 20])

(defmacro defn-common [name args & body]
  `(defn ~name ~args (let ~common-assign  ~@body)))

(defn-common foo [a b c] (+ a b c x y))


回答3:

You can use a closure for this.

(let [x 10
      y 20]
  (defn foo
    []
    (let [hello "world"]
       ...)))
  (defn bar
    []
    ...))

But, why not just refer to the values in the namespace?

(def x 10)

(def y 20)

(defn foo
  []
  (let [hello "world"]
    ...))

(defn bar
  []
  ...)