3 ms·
Whatever programming language you are using, at some point or at some representation the compiler will start generating code. The difference is that the default
by bjoli 9y ago
Whatever programming language you are using, at some point or at some representation the compiler will start generating code. The difference is that the default code representation of lisp allows it at source level, making writing (and debugging) them a lot easier. An if statement in python generates a shitload of bytecode that the optimizer then does what it pleases to. With lisp you can watch that process by watching the source->source transformations of macros and the optimizer.
Macros allow us to extend the language. It is not just C-like code generation. The loop constructs of common lisp, or the for loops of racket (or my own reimplementation for guile scheme) are macros.
With lisp macros we can express zero cost abstractions that in other languages would have a lot of overhead, and make them feel like a regular language construct (CLOS started like that)
My own racket-like loops for guile generate code that the optimizer can then turn into optimal code: https://bitbucket.org/bjoli/guile-for-loops/overview https://bitbucket.org/bjoli/guile-for-loops/overview
The downside being that macro expansion slows down compilation. My workstation can expand about 1000 loop macros/s with guile and a couple of orders of magnitude more using my chez scheme prototype (somewhere above 100k)
- jstimpfle 9y ago> An if statement in python generates a shitload of bytecode To be precise, it will generate something like 'JUMP_IF_FALSE' which is not exactly a shitload. Not saying the execution will be fast. After all, it's an interpreted language. > Macros allow us to extend the language. We're on the same page. What I was saying is: if you need more than function calls and records, chances are you're doing something wrong... the program architecture becomes intransparent. Macros and other conveniences allow for hacks put on other hacks, until you don't understand your program anymore and development eventually stalls. I once added cooperative multithreading by switching stacks in a C program. It was very easy to do and helpful for that project, but small hacks like this are rarely needed. (And in that instance it could have possibly been avoided, but I wasn't in a position to change the dataflow architecture).
- bjoli 9y agoI suspect that is just a matter of taste. I find source->source transformations pretty darn useful. You end up writing boilerplate code in all languages. Being able to just abstract that away is comfortable, and I don't really see the problem (together with what I suspect is the vast majority of lispers). You can of course provide libraries that "extend" the language, but sometimes you will never be able to lose the feeling of it being bolted on, because the semantics of the la guage doesn't lend itself to that certain way of doing it. Lisp macros solve that, at least for me. We use them like regular procedures and as long as you keep the simple rule that you sbouldnt make a macro of something you want to compose with procedures, there really isnt much that gets in the way of understanding a program, because most of the time whether something is a macro or not does not matter.