1

I would like to generate code: (nth 0 x) (nth 1 x) ... (nth n x) where x is just some variable name, and n is some number.

I'm trying do this in a following way:

(defmacro gen(n)
    (loop for i from 1 to n do
    `(nth i x))
)

Checking how it expands by: (print (macroexpand-1 '(gen 5)))

Console output is: NIL. How to do it properly?

2

2 Answers 2

2

You need to replace do with collect in your loop.

Note however that your macro captures the variable x from the calling environment.

Generally speaking, "macros are advanced material", if you are not comfortable with loop, you probably should not be writing them.

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

Comments

1

Consider what the value of the following code is:

(loop for i from 1 to 5
   do `(nth ,i x))

Since there's no collection happening, the return value of the loop is nil. If we change do to collect:

(loop for i from 1 to 5
  collect `(nth ,i x))

We see that we are getting somewhere. However, the resulting list is not actually valid Common Lisp code (and relies on there being a variable x in the environment where the macro is used).

It is not clear what you want to do with these (just run them? they're side-effect free, so just wrapping this in a progn feels somewhat useless), but you need to either cons a progn, list or similar to the front of the list of lists to make it into valid code.

(defmacro gen (n &key (var 'x) (accumulator 'list))
  (cons accumulator
    (loop for i from 1 to n
      collect `(nth ,i ,var))))

This eventually gives us this macro that seems to actually do something approaching "valid".

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.