Writing programs that generate other programs may seem esoteric, but once you learn why metaprogramming is so powerful, it’s a skill you’ll want to cultivate. This article explains why you might consider metaprogramming and looks at some of the components of this art.
I’m impressed. I expected YA (worthless) exposition of C++ template metaprogramming, but I got an overview of several different techniques, even including Scheme/Lisp, which is pretty much the only language with builtin metaprogramming worthy of the name.
Nothing here new or revolutionary here, but interesting reading and there’s likely something useful to be found.
I’m amazed they included Scheme. Syntax-case is a bit of overkill for my tastes, but that’s still incredible that Scheme got any mention.
The art perfected by virus-writers
(who use assembly code no less!)
But yeah, actually a surprisingly readable article from IBM.
Surprisingly there wasn’t any mention of C++ meta programming (using templates). It also fails to mention the really rich code generation library in .Net (which lets u generate code in any MS .Net language ), but thats ok, since this article if from IBM.
actually i thought it was a bit thin on the ground. M4? please. eeesh. nice to see some lisp but really. a SWAP macro in C pre processor??
the embedded sql was good.
Dynamic compilers easily implement metaprograms. To generate programs is just one feature. Dynamic compilers also reprogram code for optimization. The article is just one perspective without the older self-modification style view.
Jonathan Bartlett wrote it, as it mentions at the bottom, his “programming from the ground up” is good even for begginers like me.
Why its on the ibm website is something i don’t understand.
is going to be a fantastic addition to .Net 2.0…I know there’s nothing new or revolutionary about it, but we .Net folks have long been looking forward to something like this.
http://msdn2.microsoft.com/en-us/library/80h6baz2(en-US,VS.80).aspx
The ability to define out own DSL will lend itself pretty well to this paradigm also.
The Scheme example doesn’t tickle my asthetic fancy like the Common Lisp version does (sorry that OSNews borks the formatting completely):
; define vector containing square roots
(defmacro define-roots (name (start end))
`(setf ,name
(vector ,@(loop for in from start to end
collect (sqrt i)))))
; example usage
(define-roots root-table (5 20))
Doh! The third line should read:
(vector ,@(loop for i from start to end
I’d really enjoy seeing a C++ version of this macro. I’d try it myself, but I don’t think I can muster the patience
Odd that he doesn’t even mention C++ – love it or hate it, it’s still a pretty significant concentration of the meta-programming activity out there…
is quite easy in dynamic languages. I mean, I am creating new classes programmatically in ruby and python all the time, I hope this is in part two
…. TCL which is very very good for metaprogramming.
Still surprises me it didn’t catch on much better than it did.
Well, i’m no c wiz, but here is a typo I think:
#define SWAP(a, b, type) { type __tmp_c; c = b; b = a; a = c; }
should be:
#define SWAP(a, b, type) { type __tmp_c; __tmp_c = b; b = a; a = __tmp_c; }
otherwise what’s the point of ‘type __tmp_c;’
The idea of language sensitivity as implemented in Scheme is IMO the best kind of metaprogramming, but it could still be improved: Instead of using some obscure define-syntax or similar special form, they could just as well let a regular program transform the syntax, which in the end is just another data structure (and possibly transform the pattern matching of define-syntax into a general language feature). defmacro would still be the same, since it does not define a code transformer but a modified evaluator.
To explain, I’ll show how one would implement “let” this way. my-defsyntax is the special form to define code transformers, which works like defining a function but is applied automatically to code when the defined symbol is seen (this is a bit vague, I can define this more strictly if you want):
(my-defsyntax (let defs body)
(list
(list lambda (map car defs) body)
(map cdr defs)
)
)
– Morin
I’m a little confused on how this is different from defmacro. you’re example above looks like this in Common Lisp:
(defmacro mylet (defs body)
`(funcall #'(lambda ,(mapcar #’car defs) ,body)
,@(mapcar #’cadr defs)))
It can be used like:
(mylet ((a 1)(b 2)(q 3))
(format t “~A ~A ~A~%” a b q))
Semantically, it does precisely what you say. “defmacro is a special form to define code transformers, which works like defining a function but is applied automatically to code when the defined symbol is seen.”
Actually, “defmacro” is itself a macro, but the result is the same. Under the hood, “defmacro” creates a function tied to the symbol “mylet”. When the parser encounters a form like “(mylet …)”, it hands the code to that function, and subtitutes the original form with the resulting code.
In case anyone still reads this… I was referring to Scheme, where defmacro (AFAIK) defines a custom evaluator, not a code transformer. I.e. it is not a function (old code)->(new code) but a function (old environment,code)->(new environment,value)
But looks like CLISP already does what I had in mind.
– Morin