4

I want to create multiple defs in a file at compile time without having to type everything out. I'd like to do something like:

(ns itervals)

(loop [i 0]
   (if (<= i 128)
       (do 
         (def (symbol (str "i" i)) i)
         (recur (+ i 1)))))

In that way, we define the variables i1,..., i128 in the current context. I can't figure out a way to do it at compile time without defining them all explicitly. I think macros might be the way to go, but I have no idea how.

3
  • 3
    Is there a pressing reason not to just use an array? Commented Jan 18, 2011 at 6:09
  • Ditto, polluting your namespace like this is usually not a good sign. You could use a toplevel vector or hashmap. Or perhaps rework your code not to need to refer to a toplevel data structure at all. Commented Jan 18, 2011 at 9:18
  • 1
    These values will be used hundreds, if not thousands of times in a single program, so having a convenient syntax in their own namespace is simply more convenient and clear than anything else. Doing something like (iadd (inttype 32) 3 4) thousands times (where I may have to look up the cached value) is simply less efficient and clear than (iadd ty/i32 3 4). Commented Jan 20, 2011 at 0:53

2 Answers 2

7

This feels more like compile time:

(defmacro multidef[n]   
    `(do ~@(for [i (range n)]
           `(def ~(symbol (str "i" i)) ~i))))

(multidef 128)

i0   ; 0 
i127 ; 127 
i128 ; unable to resolve

But I can't think of a test that will tell the difference, so maybe the distinction is false.

Sign up to request clarification or add additional context in comments.

3 Comments

Turns out that while Jeff's version works in the REPL, it doesn't compile correctly when running unit tests.
That's probably the laziness of the for statement. Perhaps if you use doall or dotimes or doseq it will work?
That's probably the problem with Jeff's solution (aside from the gross-ness of doing this with eval at runtime). Just chiming in to say that John's is definitely the right way to do it, and that you should keep in mind the `(do ~@(whatever)) form - it turns out to be a pattern that's used in a lot of macros. If you find it more readable, you can also write it as (cons 'do (whatever))
4

Try this:

(for [i (range 1 129)]
    (eval `(def ~(symbol (str "i" i)) ~i)))

Comments

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.