3 ms·
Aren't macros breaking the homocionicity of the lisps? And making maintenance more difficult (aren't you re-inventing a new language with macros?)? Where does
by dorfsmay 12y ago
Aren't macros breaking the homocionicity of the lisps?
And making maintenance more difficult (aren't you re-inventing a new language with macros?)?
Where does the "First rule of the macro club" coming from? When should you break it?
- deleted 12y ago[deleted]
- dragonwriter 12y ago> Aren't macros breaking the homocionicity of the lisps? No. How would that be the case? > And making maintenance more difficult If used poorly, sure; the same is true of most features of most languages. > (aren't you re-inventing a new language with macros?) You are extending the existing language with them, much as you are when using a language with user-definable functions rather than only builtins.
- sjolsen 12y ago>Aren't macros breaking the homocionicity of the lisps? No. How would macros break homoiconicity? They expand into atoms and lists (and other datatypes), the same stuff of which macro-free programs are made. >And making maintenance more difficult? No. Unless you intentionally write unmaintainable macros. It's the same as if you write unmaintainable functions, classes, etc. They're just abstracting a different thing— syntax. >aren't you re-inventing a new language with macros? No, you're expanding the language; you're just expanding the grammar instead of the vocabulary. >Where does the "First rule of the macro club" coming from? When should you break it? What is the "first rule of the macro club?"
- roryokane 12y agoI have heard the “first rule of the macro club” to be “don’t write macros”. The idea is before writing a macro, you should try writing it as a function instead. If that is possible, that is usually better, because functions, unlike macros, can be passed around as first-class values, and I think they are easier to debug. You should break that rule only when the behavior can’t be written as a function, such as these cases: • The call needs to avoid evaluating its arguments. For example, the `if` built into the language is sometimes defined as a macro. (if (= (+ 2 2) 4) (print "math works") (print "math is broken")) If `if` were a function, it would first print both statements, and then return the return value of `print` in whichever branch. By making `if` a macro, it can avoid evaluating the branch that is inapplicable. • The call relies on information about the environment only available at compile-time. Perhaps the macro reads a configuration file on the developer’s computer to decide how to set something up. • You have profiled the program and determined that it is better to run the function at compile-time. For example, you might want to make `(regex "[a-z][a-z0-9]+")` compile the string to a regular expression at compile-time instead of run-time.
- sjolsen 12y ago>You have profiled the program and determined that it is better to run the function at compile-time. For example, you might want to make `(regex "[a-z][a-z0-9]+")` compile the string to a regular expression at compile-time instead of run-time I think it would be more appropriate to use a compiler macro here.
- xamuel 12y ago>maintenance If used right, macros make things much more maintainable. If you have a hundred nearly-identical codeblocks, where only (say) a string constant is varying, and suddenly you need to change what those blocks do, bam, you've got a hundred blocks to change. If those blocks had been refactored with a macro, all you have to do is change the macro once. It also prevents the new guy from coming and doing a bandaid fix to line #72 making it slightly different from the 99 lines around it and making your life a living hell.
- dorfsmay 12y agoNot a lisper, so bear with me please. Couldn't you do this with a function?
- roryokane 12y agoYes, you could do that with a function. I think that was a bad example. I listed some situations where you need a macro in my comment that explains the “first rule of the macro club” you asked about: https://news.ycombinator.com/edit?id=9513988 https://news.ycombinator.com/edit?id=9513988
- xamuel 12y agoThe code block in question might be something that doesn't really deserve a whole function on its own, and could also involve local control-flow statements (return/continue/break/etc.) that can't really be outsourced to a function nicely. For example, you're parsing a line from a flat file and you want to assign a value to a certain variable based on the first word on the line. So you have a few dozen/a hundred lines of if ( key == "hitpoints" ) {player.hitpoints = value; return;} if ( key == "mana" ) {player.mana = value; return;} Those "return"s make it rather awkward to use a function. At best, said function would have to return a bool and you'd end up with something like if ( maybe_assign( key, "hitpoints", &player.mana ) ) return; which hardly gains you anything and in fact reduces readability a fair amount.