People like GP often repeat that talking point: "code is data so that's amazing because of macros".
In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
Macros can almost always be expressed with a simple function and remove all the unexpectedness without losing anything. Again, there are some exceptions.
> In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
I'm not sure "frowned upon" is the right expression, but I'm not a native speaker.
The way I've internalized it, is basically "Avoid macros unless there is no other way", which basically means use functions/anything else whenever you can, but if you absolutely have to use a macro for something (like you wanna read the arguments before they're parsed), then go for it.
I always looked at these features of being able to extend the language beyond some commonly accepted practices as detrimental to the language. I've spent way too much time debugging issues with operator overloading or complex templates (C++), or obscure side effects in DSLs. So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
But... looks like the professional community knows this and so maybe it's time to take a deeper dive :)
> So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
It can be, but also not. If you isolate them into libraries with clear interfaces, you can kind of avoid that. I think clojure.core.async is an excellent showcase in something you couldn't do in other languages, where asynchronous channels were possible to add to the core language without changing anything in the core compiler itself, and because of the small interface, you can still use it without ending up with nightmares :)
Understood. I was more referring to a case where a project would start defining its own language constructs and if each project would do that then every single project would come with a very high cognitive load.
Dunno about the Clojure communtity but for Emacs Lisp and Common Lisp there are certain broadly accepted idioms where macros are accepted:
1. "with-context", where there is a need to control resource allocation/deallocation or things in the context of code in question.
2. use-package dsl that simplify configuration in a predictable way
3. object definition helpersresource
Then, there are core language extensions and std libraries suggested for the main implementation. This is where macros are fine as they always get good documentation and plenty of additional eyeballs.
People like GP often repeat that talking point: "code is data so that's amazing because of macros".
In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
Macros can almost always be expressed with a simple function and remove all the unexpectedness without losing anything. Again, there are some exceptions.