Live data from Hacker News

How Lisp macros differ from static code-generation and metaprogramming

brandonbyars.com

41–50 of 84 posts

Re: How Lisp macros differ from static code-generation and metaprogramming

#41

Earlier quoted context omitted.

The reason Linux trace macros are insane is because C preprocessor is so primitive. 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!

Note, the power of the macro system is not equal to its general good. The C macro system was already too powerful, and one of the things that hurts languages is a preprocessor of virtually any kind. The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way. The benefit from the preprocessor is absurdly small. Wit…

The C preprocessor can't do metaprogramming, by definition - there's no way to take apart and examine the arguments passed to macros.

The reason you can't statically analyze C code that uses macros has to do with the preprocessor's broken design - it is a separate stage from the compiler, and there's no way for the two to communicate.

All this actually means that Lisp macros can be used for static analysis (via macroexpand), in a user-extensible way, without needing to add extensions to the compiler or stages to the compilation process.

I don't understand why you cite C# as a good example of something that doesn't have code preprocessors. Visual Studio has T4 (Text Template Transformation Toolkit), which is a dumb joke.

Re: How Lisp macros differ from static code-generation and metaprogramming

#42

Earlier quoted context omitted.

Note, the power of the macro system is not equal to its general good. The C macro system was already too powerful, and one of the things that hurts languages is a preprocessor of virtually any kind. The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way. The benefit from the preprocessor is absurdly small. Wit…

Does everyone just troll now?

Apparently so.

Re: How Lisp macros differ from static code-generation and metaprogramming

#43
post #41

Earlier quoted context omitted.

Note, the power of the macro system is not equal to its general good. The C macro system was already too powerful, and one of the things that hurts languages is a preprocessor of virtually any kind. The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way. The benefit from the preprocessor is absurdly small. Wit…

The C preprocessor can't do metaprogramming, by definition - there's no way to take apart and examine the arguments passed to macros. The reason you can't statically analyze C code that uses macros has to do with the preprocessor's broken design - it is a separate stage from the compiler, and there's no way for the two to communicate. All this actually means that Lisp macros can be used for static analysis (via macro…

First, the use case for T4 is fundamentally different than language macros. You would't use Lisp macros or C macros for what you'd do with T4. For example, I've seen T4 used to do some elaborate documentation generation.

But back to the point, I partially agree with what you say about C, but I think you misunderstand where the crux of the problem. It's not that they're separate stages -- I believe they are in most Lisp implementations (but I may be wrong), but rather that you can't do macro expansion w/o the context of the full program, i.e., within the context of the build system -- yet the effect is global.

Re: How Lisp macros differ from static code-generation and metaprogramming

#44

Earlier quoted context omitted.

The reason Linux trace macros are insane is because C preprocessor is so primitive. 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!

Note, the power of the macro system is not equal to its general good. The C macro system was already too powerful, and one of the things that hurts languages is a preprocessor of virtually any kind. The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way. The benefit from the preprocessor is absurdly small. Wit…

> Note, the power of the macro system is not equal to its general good.

It's hard to quantify "general good" of something complex as programming language macro system with all consequences included.

But it's quite easy to see which one is more powerful wrt expressiveness.

Your primitive macro system _forces_ me to write code like this:

#ifdef CONFIG_AUDITSYSCALL #define INIT_IDS \ .loginuid = -1, \ .sessionid = -1, #else #define INIT_IDS #endif

#define INIT_TASK(tsk) \ { INIT_IDS }

instead of more natural.

#define INIT_TASK(tsk) \ {\ #ifdef CONFIG_AUDITSYSCALL .loginuid = -1, \ .sessionid = -1,\ #endif }

> The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way.

Static analysis hardness or easyness has _nothing_ to do with preprocessing, because static analyzer can preprocess code in a very same way compiler will so both will analyze the very same stream of tokens.

> The benefit from the preprocessor is absurdly small.

This is subjective and unquantifiable.

Re: How Lisp macros differ from static code-generation and metaprogramming

#45
Seeing how this guy comments about loop, be a little careful when using it. There is no formal standard on how to implement loop, so what you write might result in different answers depending on what Common Lisp implementation you use. Evaluate these loop-expressions and see what happens (from ANSI Common Lisp by PG):

    (loop for y = 0 then z
          for x from 1 to 5
          sum 1 into z
          finally (return (values y z)))
          
and then evaluate this:

    (loop for x from 1 to 5
          for y = 0 then z
          sum 1 into z
          finally (return (values y z)))

Re: How Lisp macros differ from static code-generation and metaprogramming

#46

Earlier quoted context omitted.

The reason Linux trace macros are insane is because C preprocessor is so primitive. 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!

Note, the power of the macro system is not equal to its general good. The C macro system was already too powerful, and one of the things that hurts languages is a preprocessor of virtually any kind. The badness of the C preprocessor starts much earlier with things like include files, and the fact that you can't statically analyze the code in any reasonable way. The benefit from the preprocessor is absurdly small. Wit…

   In a decade or less, the Lispers will see this light too.
Right. It's just been invisible for the last 25 years. Or maybe the last 50. Whatever. One of these days...

Re: How Lisp macros differ from static code-generation and metaprogramming

#47
post #38
post #26

Earlier quoted context omitted.

Even early stabs at x-bar theory indicate that natural languages are highly homoiconic. http://en.wikipedia.org/wiki/X-bar_theory

Can you please explain more?

Homoiconicity means program and data have identical representation. But after you Lisp for a while the boundary blurs entirely.

X-bar theory says that in all natural languages, Noun Phrases, Verb Phrases, and depending on who you read other types of phrases all have the same form; a single Head (which may be composite) and a Tail with zero or more elements. Never mind that they've just discovered S-expressions. The point is that in the natural language program:

    multiply the radius squared and pi
Both the data-like parts and the program-like parts share the same structure.

Re: How Lisp macros differ from static code-generation and metaprogramming

#48
So Lisp macros provide compile-time code generation, but in doing so, you have access not just to the code-generation instructions – which are just Lisp data – but also to the entire Lisp language and environment.

The same can be said for classic Forth. Indeed, the enthusiastic way that Lispers describe macros I find eerily similar to how I used to hear Forthians describe their language. Except in Forth the relevant term isn't macro but "defining word". Indeed, I think programmers in both camps see the proper use of macros/defining words as a sign that one has passed the beginner stage of using the language.

A classic compiled Forth word (ie, function) would consist of the word's name followed a string of addresses to execute; how those addresses were laid down, where they pointed, etc. were totally open to programmer control -- both during compilation and afterwards. It's been a couple of decades since I looked at Forth code, but I don't think there's anything that could be done in Lisp macros that couldn't also be done easily in Forth as well.

I think the big difference between the two -- at least, so far as the macro topic goes -- is that Lisp starts with an assumption that code and data can and should be interchangeable while Forth was initially developed for the machine control (embedded systems before they were called embedded systems) and thus code was merely a vehicle for creating applications.

Re: How Lisp macros differ from static code-generation and metaprogramming

#49
post #3

By 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…

I like Conrad Barski's take on explaining quasiquote:

http://www.lisperati.com/looking.html

"Flip, flop, flip, flop..."

Post reply on HN