4

I have many functions of the same long signature (shortened here for simplicity):

(defn f 
      [x & {:keys [a b c d e f g h]
            :or [a false b false c false d false e false f false g false h false]}]
      a)

I was hoping to use a macro, function, or even a def to store this common signature beforehand:

(def args `[a b c d e f g h])

(defn args [] `[a b c d e f g h])

(defmacro args [] `[a b c d e f g h])

but all of them, when I plugged into

(defn f 
      [x & {:keys (args)
            :or [a false b false c false d false e false f false g false h false]}]
      a) 

ended up with errors like

CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:1) 

So my two questions are:

  1. Is there any way to define and use such a common args?

  2. If such an args can be defined, I would also like to reduce it in order to get the :or params: [a false b false c false d false e false f false g false h false]. How would this be done? (I'm asking in case a working definition of args might be weird enough that this is no longer straightforward.)

spacingissue
  • 497
  • 2
  • 12

1 Answers1

6

The problem is that the stuff inside the argument vector in a defn doesn't get evaluated. However, you can define your own version of defn, like so:

user=> (defmacro mydefn [name & body] `(defn ~name ~'[a b c] ~@body))
#'user/mydefn
user=> (mydefn f (+ a b))
#'user/f
user=> (f 1 2 4)
3

Note the need for ~' for the arguments. Otherwise syntax-quote (`) would qualify the symbols into user.a etc.

opqdonut
  • 5,119
  • 22
  • 25