5 ms·
#define foreach(x, xs) \ for(var x = iter_start(xs); x = iter_next(xs); x != iter_end(xs)) It's all C: http://libcello.org/documentation/hacking http://lib
by mcpherrinm 13y ago
#define foreach(x, xs) \
for(var x = iter_start(xs); x = iter_next(xs); x != iter_end(xs))
It's all C: http://libcello.org/documentation/hacking http://libcello.org/documentation/hacking
- kragen 13y agoImagine what happens when someone says foreach(x, get_next(queue)) f(x); To solve this problem, with GCC, you have the option of defining foreach as { typeof (xs) _xs = xs; \ for (var x = iter_start(_xs); x = iter_next(_xs); x != iter_end(_xs)) but then you need a corresponding endforeach to apply the matching }. If you just leave off the opening {, then you end up with a mysterious compile error on if (ready(queue)) foreach(x, get_next(queue)) f(x); since the declaration of _xs is not a statement. And this kind of thing is why a "macro system" means something very different in C and in Lisp, and why Brad Cox wrote a compiler in 1983 instead of a macro library.
- dfbrown 13y agoYou could do #define foreach(x, xs) \ for (var _xs = xs, *x = iter_start(_xs); x = iter_next(_xs); x != iter_end(_xs)) Because var is just void* and anything you can iterate over will also be a void*.
- kragen 13y agoOh, that's excellent! I don't know why the C9x for-declaration didn't occur to me as a possible solution, particularly since the macro was already using it. You should submit this as a fix!