For example, Python’s if and not are macros. You can’t write your own ifnot macro to abbreviate if and not because you’re not allowed to write your own macros.
Here’s how you do it with the C preprocessor.
#define ifnot(x) if(!x)
You can apply this trick to any language with a textual representation, since preprocessing is a separate stage.
I considered putting in a footnote acknowledging the existence of this kind of textual macro in languages like C and Bash. Demonstrating the uniqueness of defmacro requires a more sophisticated example, like embedding Haskell.
Edit: I replied to the wrong comment. This was supposed to be a reply to TAG’s parent comment.
I considered putting in a footnote acknowledging the existence of this kind of textual macro in languages like C and Bash. Demonstrating the uniqueness of defmacro requires a more sophisticated example, like embedding Haskell. Even if you can do this in C, you shouldn’t.
I was being a bit tongue in cheek about the macro thing. You can apply macros, in the sense of a preprocessor expanding text, to anything.
Defmacro isn’t unique,but not just because of preprocessors. Less vaunted languages such as Forth can also define fundamental new keywords.
The uniqueness claim, apart from being false, is an unnecessary restriction. There are ways of achieving the things that lisp can achieve that dont have its downsides.
I think a relevant difference between Lisp macros and textual macros of other languages is that in Lisp, the program is in the form of a datastructure (a list) that has relevant structure. So the macro is manipulating data at a level that is more relevant than text.
Thinking that there is not such a relevant difference might contribute to antimeminess of Lisp imo.
Aside:
I think what would be even better would be macros in a language where not only is the program in the form of a datastructure with relevant structure, but the language is also statically typed (with a suitably complex type system) with any program or subprogram having a type. The compiler could then provide protection against mistakes, allowing more complex stuff to be done in practice. Haskell partially does this by defining types for functions and allowing you to make functions that spit out other functions, but (afaik) doesn’t apply this to other aspects of Haskell programs which seems to me a huge wasted opportunity.
I think both Template Haskell and MetaOCaml have some typechecking of macros.
Though I haven’t found macros very useful or exciting. To me the most fun way to program is with simple code, but relying on a lot of implicit understanding. Something like what Kragen describes here:
Also, sometime around 1993, I read Robert Sedgewick’s textbook, “Algorithms in C”, which I borrowed from my father, Greg Sittler. It opened a whole new world to me. The programs in the book are all concise crystals of beauty, showing how a few lines of code can transform a pile of structs of integers and pointers into a binary search tree, or a hash table, or the minimal spanning tree of a set of points. It used only the basics of C, and did not rely on any libraries.
This was a revelation to me; there was beauty and magic in these programs, and it wasn’t because they were calling on powerful libraries hidden, Wizard-of-Oz-style, behind curtains. They were just plain C code, and not very much of it, that “developed a set of operations that were not obviously implicit in the original set,” to borrow Bruce Mills’s phrase.
Yes. There’s nothing magic about a list as a data structure that allows you to do implement type-safe macros. In fact, since any code can be represented as an abstact syntax tree, a tree-like data structure would be more general. I beleive the Nim language works that way.
Here’s how you do it with the C preprocessor.
#define ifnot(x) if(!x)
You can apply this trick to any language with a textual representation, since preprocessing is a separate stage.
Pedantic note: you should do
#define ifnot(x) if (!(x))
(with extra parens around the second instance of “x”) because otherwise you will get probably-unexpected results if x is something like a==b.
You’re right, I’m rusty.
I considered putting in a footnote acknowledging the existence of this kind of textual macro in languages like C and Bash. Demonstrating the uniqueness of
defmacro
requires a more sophisticated example, like embedding Haskell.Edit: I replied to the wrong comment. This was supposed to be a reply to TAG’s parent comment.
I considered putting in a footnote acknowledging the existence of this kind of textual macro in languages like C and Bash. Demonstrating the uniqueness of
defmacro
requires a more sophisticated example, like embedding Haskell. Even if you can do this in C, you shouldn’t.You shouldn’t do this in C.
I was being a bit tongue in cheek about the macro thing. You can apply macros, in the sense of a preprocessor expanding text, to anything.
Defmacro isn’t unique,but not just because of preprocessors. Less vaunted languages such as Forth can also define fundamental new keywords.
The uniqueness claim, apart from being false, is an unnecessary restriction. There are ways of achieving the things that lisp can achieve that dont have its downsides.
I think a relevant difference between Lisp macros and textual macros of other languages is that in Lisp, the program is in the form of a datastructure (a list) that has relevant structure. So the macro is manipulating data at a level that is more relevant than text.
Thinking that there is not such a relevant difference might contribute to antimeminess of Lisp imo.
Aside:
I think what would be even better would be macros in a language where not only is the program in the form of a datastructure with relevant structure, but the language is also statically typed (with a suitably complex type system) with any program or subprogram having a type. The compiler could then provide protection against mistakes, allowing more complex stuff to be done in practice. Haskell partially does this by defining types for functions and allowing you to make functions that spit out other functions, but (afaik) doesn’t apply this to other aspects of Haskell programs which seems to me a huge wasted opportunity.
I think both Template Haskell and MetaOCaml have some typechecking of macros.
Though I haven’t found macros very useful or exciting. To me the most fun way to program is with simple code, but relying on a lot of implicit understanding. Something like what Kragen describes here:
Yes. There’s nothing magic about a list as a data structure that allows you to do implement type-safe macros. In fact, since any code can be represented as an abstact syntax tree, a tree-like data structure would be more general. I beleive the Nim language works that way.