Earlier quoted context omitted.
1. Macros aren't unique to lisp. Perl6 also has macros ( http://en.wikipedia.org/wiki/Perl_6#Macros ) though they haven't been implemented in Rakudo yet. Also Ioke states that it has macros. 2. Metaprogramming's power ... The best example I know of is Io where pretty much anything other than commas and parentheses... Touched on Io introspection/metaprogramming before on HN: * http://news.ycombinator.com/item?id=18045…
The question isn't so much whether other languages have something they call "macros", but whether their macro systems approach Lisp's in power, flexibility, ease of use, integration with the language, and natural fit on to the language representation? Or is the macro system in question more of a Turing tarpit?
How Lisp macros differ from static code-generation and metaprogramming
21–30 of 84 posts
Re: How Lisp macros differ from static code-generation and metaprogramming
#22Nice try blanco niño, but the following program runs fine. This doesn't detract from your overall point, but if you're trying to win over people who think the Boost macros are super awesome, this argument won't do it. #include #define LOOP(n) \ int i; \ for (i = 0; i #define LOOP10 \ LOOP(10) printf("%d\n", i) int main(int argc, char *argv[]) { LOOP10; }
Yesterday I was writing code that kept messing my Lisp's signal handling, so I wrote a FOR-DURATION macro that arms a timeout and makes sure whatever that runs in its body gets killed after N seconds. Here it is: (defmacro for-duration ((seconds) &body body) `(handler-case (bt:with-timeout (,seconds) ,@body) (bt:timeout () nil))) Five lines to alter the evaluation model of your language. Not bad. Use as: (for-duratio…
#define for_duration(seconds, body) \
{ \
pthread_t tid_task, tid_watcher; \
\
void* task(void* arg) { \
body ; \
pthread_cancel(tid_watcher); \
return NULL; \
} \
\
void* watcher(void* arg) { \
sleep((seconds)); \
pthread_cancel(tid_task); \
return NULL; \
} \
\
pthread_create(&tid_task, NULL, &task, NULL); \
pthread_create(&tid_watcher, NULL, &watcher, NULL); \
pthread_join(tid_task, NULL); \
}
Use as: for_duration(10, {
while (true) {
printf("Infinite loop! where is your Godel now?\n");
}
});
Or with single brace-less statements: for_duration(10, while (true) printf("something\n") );
Lexical scope is sane: int i = 0;
for_duration(10, {
while (true) {
printf("%d\n", i++);
}
});
My comparison isn't quite fair, because your threading library provides 'with-timeout', while pthreads doesn't. If you factored this out, say with a signature like: void with_timeout(unsigned int seconds, void (*func)(void));
(in analogy to the common lisp function), then the macro part becomes just four lines: #define for_duration(seconds, body) { \
void func() { body ; } \
with_timeout((seconds), &func); \
}
I acknowledge that the lisp solution is rather more elegant. Also, my C macro is potentially dangerous because it is unhygenic. (It shadows outer declarations of 'task()', 'watcher()', 'tid_task', 'tid_watcher', and 'arg', in the body of 'body'.)Re: How Lisp macros differ from static code-generation and metaprogramming
#23By the way, don't confuse macros with backquote; the backquote facility is probably closer to C's preprocessors. I haven't heard this claim before, and I might not be entirely right, but it's what provides for the "fill in the blanks" type symbolic computing. For example: (defun sum (x y) `(,x + ,y = ,(+ x y))) This is a SUM function which looks like this when run: (sum 4 5) ==> (4 + 5 = 9) The backquote (`) says the…
You can also splice values into backquoted expressions using ,@foo rather than ,foo - which I seem to remember being rather useful.
(mac until (test . body)
`(while (no ,test) ,@body))
It's really useful for bodies of code like this.Re: How Lisp macros differ from static code-generation and metaprogramming
#24> Except, of course, that doesn’t work. The preprocessor only makes one pass > through the file, meaning a macro can’t call another macro. Huh? That's just blatantly wrong, and I (and many others) have used the C preprocessor to create multi-level macros in quite powerful ways. See for example http://blog.nelhage.com/2010/07/implementing-an-edsl-in-cpp/ or the insanity Linux's tracing macros have implemented: http://…
Think about it.
> they are quite powerful
For small values of "quite". C macros are strictly less (and by large margin powerful than Lisp macros. One can't even use #ifdef inside #define!
Re: How Lisp macros differ from static code-generation and metaprogramming
#25Earlier quoted context omitted.
Yesterday I was writing code that kept messing my Lisp's signal handling, so I wrote a FOR-DURATION macro that arms a timeout and makes sure whatever that runs in its body gets killed after N seconds. Here it is: (defmacro for-duration ((seconds) &body body) `(handler-case (bt:with-timeout (,seconds) ,@body) (bt:timeout () nil))) Five lines to alter the evaluation model of your language. Not bad. Use as: (for-duratio…
C99 + GCC extensions + POSIX: #define for_duration(seconds, body) \ { \ pthread_t tid_task, tid_watcher; \ \ void* task(void* arg) { \ body ; \ pthread_cancel(tid_watcher); \ return NULL; \ } \ \ void* watcher(void* arg) { \ sleep((seconds)); \ pthread_cancel(tid_task); \ return NULL; \ } \ \ pthread_create(&tid_task, NULL, &task, NULL); \ pthread_create(&tid_watcher, NULL, &watcher, NULL); \ pthread_join(tid_task, N…
Re: How Lisp macros differ from static code-generation and metaprogramming
#26Are natural languages homoiconic? (If you get my drift.) Does that question even make sense?
Re: How Lisp macros differ from static code-generation and metaprogramming
#27Earlier quoted context omitted.
Yesterday I was writing code that kept messing my Lisp's signal handling, so I wrote a FOR-DURATION macro that arms a timeout and makes sure whatever that runs in its body gets killed after N seconds. Here it is: (defmacro for-duration ((seconds) &body body) `(handler-case (bt:with-timeout (,seconds) ,@body) (bt:timeout () nil))) Five lines to alter the evaluation model of your language. Not bad. Use as: (for-duratio…
(defun for-duration (seconds body) (handler-case (bt:with-timeout seconds (body)) (bt:timeout () nil))) (for-duration 10 (lambda () (loop (print "Infinite loop! where is your Godel now?"))))
Re: How Lisp macros differ from static code-generation and metaprogramming
#28Earlier quoted context omitted.
C99 + GCC extensions + POSIX: #define for_duration(seconds, body) \ { \ pthread_t tid_task, tid_watcher; \ \ void* task(void* arg) { \ body ; \ pthread_cancel(tid_watcher); \ return NULL; \ } \ \ void* watcher(void* arg) { \ sleep((seconds)); \ pthread_cancel(tid_task); \ return NULL; \ } \ \ pthread_create(&tid_task, NULL, &task, NULL); \ pthread_create(&tid_watcher, NULL, &watcher, NULL); \ pthread_join(tid_task, N…
I don't believe nested functions like you're using there are valid C. They're a nonstandard extension that some compilers implement because they're so handy. So this basically illustrates that C gets closer Lisp's usability when you add Lispy features to it.
Re: How Lisp macros differ from static code-generation and metaprogramming
#29A couple points on the metaprogramming space (these aren't about the article, but the article reminded me of them): 1. Macros aren't unique to lisp. They're most developed and used in the lisp family, but you don't need to have a homoiconic language to have macros. The Mirah programming language--statically typed Ruby on the JVM--has non-hygenic macros, I know there's been a number of efforts to add macros to coffees…
1. Yet, still to this day, Lisp remains one of the few languages with powerful macros that normal people cannot only use, but enjoy. Also the Scheme/Racket community actively researches how to make them more robust and easier to write (yes equally powerful macro systems do exist for other languages - however, ease of use is often sacrificed) 2. Io is great but the depth of it's runtime meta-programming facilities mak…
As for Io's efficiency, I think that's more about the implementation than in the language. Javascript (prototypal inheritance) and Smalltalk (message passing) aren't that far off and both have decent performance. I know Steve Dekorte was working on getting Io running in javascript in December but I don't think it's a high priority project for him.
Re: How Lisp macros differ from static code-generation and metaprogramming
#30A couple points on the metaprogramming space (these aren't about the article, but the article reminded me of them): 1. Macros aren't unique to lisp. They're most developed and used in the lisp family, but you don't need to have a homoiconic language to have macros. The Mirah programming language--statically typed Ruby on the JVM--has non-hygenic macros, I know there's been a number of efforts to add macros to coffees…