3

I have a series of functions that all do different things but are passed the same data. Let's say I have the following as a parameter vector.

[{:keys [x y vx vy x-min x-max y-min y-max] :or {x-min 0 x-max c-width y-min 0 y-max c-height}}]

Basically the type of thing you do not want to have to repeat more than once. One thought I had was to do something like.

(def func-args [x y z])
(defn func func-args (+ x y z))

Then I could re-use func-args if I had a similar function. However the first line of the previous example throws an error that symbol x cannot be resolved.

  • Is there a way to leave vector members as symbols?
  • Is there a more idiomatic way to accomplish function parameter code bloat reduction than the method I am suggesting?
2
  • If you bind those vector values, you'll avoid the error you're getting. Commented Nov 23, 2016 at 16:31
  • 2
    Perhaps the real problem here is that with all of those arguments, your functions are too complex. Commented Nov 23, 2016 at 16:55

2 Answers 2

6

Quoting a vector will leave it's symbols unevaluated, however defn expects a literal vector in the definition, so this won't work like you're suggesting.

The easiest way to do this is to create a macro. Macros let you create your own syntax. This kind of (anaphoric) macro is discouraged in Clojure as it's easy to run into problems with macros that create symbols for you.

Something like:

(def cheight 100)
(def cwidth 100)
(defmacro defx [name & body]
  `(defn ~name [{:keys [~'x ~'y ~'vx ~'vy ~'x-min ~'x-max ~'y-min ~'y-max] 
                 :or {~'x-min 0 ~'x-max ~'c-width ~'y-min 0 ~'y-max ~'c-height}}]
     ~@body))

(defx func (+ x y))

(func {:x 1 :y 2}) ;; 3
Sign up to request clarification or add additional context in comments.

Comments

2

Here is another way of doing it that accepts the function args spec vector as a parameter to the macro:

(defmacro defn-args
  [fn-name fn-args & forms]
  `(defn ~fn-name ~(eval fn-args) ~@forms))

(def square-args '[x] )    ; must quote [x] here
(defn-args my-square square-args (* x x))

(my-square 3) 
;=> 9

1 Comment

This is a very concise method that only uses one macro for all cases.

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.