Jump to content
  • Advertisement
Sign in to follow this  
Brobanx

LISP Gods, is this possible?

This topic is 4603 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to write my own version of the 'dotimes' macro, which will repeat a statement (or block of statements) x number of times. However, if you supply a constant, I want to it repeat the statement x times and have it expand to
(progn
   (statement1)
   (statement2)
   (statement3)
   ....
   (statementx))


Right now, I have it seperated into two seperate macros, one of which just inserts a do, and does a loop from 0 to x-1. The other actually repeats the statement x times and puts the expansion inside a progn block like shown above. The first one will work with any value. The second one will only work with numerical constants. This is the correct behaviour, however, I need two seperate macros, and I think that's ugly. Is there any way for me to tell if the given value is a compile-time (macro-expansion time) constant? I've tried different combinations of numberp, symbolp, and boundp, none of which seem to work. The problem is I can't call numberp / symbolp on a symbol that isn't bound yet (none of hte symbols are bound during macro-expansion time), and I can't call boundp on an integer or (quote integer). Any suggestions? The constant version
(defmacro mydotimes-helper (n continuation body)
      (if (= n 0)
          `(progn ,@continuation)
          `(mydotimes-helper ,(1- n) ,(append continuation body) ,body)))

(defmacro mydotimes (n &rest body)
    `(mydotimes-helper ,n () ,body))

The non-constant version just calls the existing standard dotimes macro. (boundp 6) ERROR (boundp '6) ERROR (numberp f) ERROR (every symbol seems to be unbound during macro-expansion time) (numberp 'f) NIL

Share this post


Link to post
Share on other sites
Advertisement
I'm a bit sleepy atm but shouldn't the following work?

(defmacro footimes (arg &body body)
(if (symbolp arg)
`(dotimes (,(gensym) ,arg)
,@body)
(cons 'progn
(loop for i from 0 to arg collect
(car body)))))


Since the argument symbol is interned at readtime you should be able to use symbolp to check it.

Share this post


Link to post
Share on other sites
Ok, symbolp works =].

Quote:
Original post by Flatlander
Since the argument symbol is interned at readtime ...


I didn't think the symbols were interned at readtime. I feel very sheepish.


(defmacro footimes ((i arg) &body body)
(if (symbolp arg)
`(dotimes (,i ,arg)
,@body)
(cons 'progn (append
(loop for x from 0 to (- arg 1) collect
`(let ((,i ,x)) ,@body))
(list ())))))




The above code works perfectly. Now I'm just wondering how to get this to over-ride the default dotimes() macro. THe problem is, it relies on dotimes. I'm having trouble getting macrolet to let me rename the original dotimes to something like old-dotimes.

Share this post


Link to post
Share on other sites
Redefining contents(like DOTIMES) of COMMON-LISP package has undefined consequences. Instead you should make a new package (DEFPACKAGE) and define your own DOTIMES in there. Then you can refer to the original DOTIMES as CL:DOTIMES.
See
http://www.lisp.org/HyperSpec/Body/chap-11.html
http://gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html

If you are doing this as an optimization perhaps you should reconsider your approach. Where this kind of loop unrolling would have an effect a decent compiler should do it automatically for you. I would be curious to know if it really has an positive effect on performance on some implementation/situation.

Share this post


Link to post
Share on other sites
Shouldn't you use something besides symbolp since you could also include an expression (that would be evaluated after the macro)? In other words, it should be something like
if(not number) {insert dotimes} else {repeat statement [number] times}
Unfortunately, I my Lisp reference isn't available at the moment and it's been so long since I've used Lisp that I can't remeber the name of the predicate to test for an integer.

Share this post


Link to post
Share on other sites
Ok, (not (numberp arg)) works correnctly, it handles arbitrary expressions properly.

I'm not seriously trying to do this as an optimization, I'm well aware that the compiler does this kind of thing for you. I'm just testing out the possibilities of Common Lisp macros, I'm still deciding whether to use Common Lisp or something like Scheme/Dylan for some small projects, but so far I've found that Scheme/Dylan macros simply aren't capable of some of the things that Common Lisp macros are. For instance, the above macro has no equivalent in Scheme or Dylan.

As for overriding the original macro, it's certainly bad practice, but I'd like to know if it's possible, and how to overwrite an existing macro (say, if I ever wanted to add some kind of automatic logging functionality to certain macros).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!