Starting with your recent version, which is at least a reasonable candidate for a macro unlike the older one:
(defmacro foo (someExpression count-var)
`(do ((,count-var 0 (+ ,count 1)))
((= ,count-var 5) T)
`(eval (,someExpression))))
Well what is the expansion of (foo (print 1) c)
?
(foo (print 1) x)
-> (do ((x 0 (+ x 1))) ((= x 5) t)
`(eval (,someexpression)))
Well, that's a disaster: what is that nested backquote doing? Let's just remove it:
(defmacro foo (someExpression count-var)
`(do ((,count-var 0 (+ ,count 1)))
((= ,count-var 5) T)
(eval (,someExpression))))
(foo (print 1) x)
-> (do ((x 0 (+ x 1))) ((= x 5) t)
(eval ((print 1))))
That's less disastrous, but the eval
form is entirely bogus. We can make that 'work' by changing it to be at least syntactically legal:
(defmacro foo (someExpression count)
`(do ((,count 0 (+ ,count 1)))
((= ,count 5) T)
(eval ,someExpression)))
And now
(foo (print 1) x)
-> (do ((x 0 (+ x 1))) ((= x 5) t)
(eval (print 1)))
And this will 'work' but it will work purely by coincidence: because (print 1)
returns 1
and the value of 1
is 1
.
(foo (print 'foo) x)
-> (do ((x 0 (+ x 1))) ((= x 5) t)
(eval (print 'foo)))
and that's a run-time error.
But ... why are you using eval
? eval
is a terrible, terrible solution to almost any problem you can think of, unless the solution to the problem is called 'code injection attack', and in this case it's not just terrible: it's wrong. So we just remove it.
(defmacro foo (someExpression count)
`(do ((,count 0 (+ ,count 1)))
((= ,count 5) T)
,someExpression))
And now
(foo (print 'foo) x)
-> (do ((x 0 (+ x 1))) ((= x 5) t)
(print 'foo))
Which looks like the code transformation we want. So, finally:
> (foo (print 'foo) x)
foo
foo
foo
foo
foo
t
Which is, finally, fine. And this works:
> (foo (print x) x)
0
1
2
3
4
t
As with yet another edit to the question it probably is more useful to put the variable name first and allow a bunch of expressions:
(defmacro foo (count-var &body forms)
`(do ((,count-var 0 (+ ,count-var 1)))
((= ,count-var 5))
,@forms))
This will now allow multiple expressions in the body. And we could go further: we could allow it to specify the number of iterations and the return value`:
(defmacro foo ((count-var &optional (count 1) (value 'nil)) &body forms)
`(do ((,count-var 0 (1+ ,count-var)))
((= ,count-var ,count) ,value)
,@forms))
And now
> (foo (x 2)
(print x)
(print (* x 2)))
0
0
1
2
nil
Well, the name of this macro is dotimes
of course.