Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> (do-texture texture > o O r R x2)

This might be another reason why I find macros less appealing: macros introduce DSL in form of normal s-expression, but they don't actually behave like a function; macros introduce their own mini-language/syntax.

In the last example you provided, I bet the macro implementation would look like a little interpreter? If that's the case, having a function call like

  doTexture(myTexture, ['op1', 'op0', 'opR'])
and let doTexture handle each cases(ops), might be able to achieve the same behavior, right?

I'm not trying to argue that macros are unnecessary, I really want to like them! Just most of the time, I find functions are sufficient enough.



Remember JavaScript before "async"? Lots of boilerplate there. You had to wait until some committee decided to incorporate it into the language.

So "modern" languages without macros have such patches every now and then. Still, it's easy to find boilerplate in programs.

The reason is that a lot of boilerplate is specific to the program's domain, and you're left with cumbersome syntactic patterns and no tools to abstract them.

So yes, you need to learn how to write macros. But, assuming good taste, the simplicity is in their use, not their definition. It's a good tradeoff because macros are used much more often than they are defined.

By the way, the language introduced by a macro often allows arbitrary Lisp code to be mixed with it. The example did not demonstrate this, and that's why you had an easy time thinking up a non-macro alternative (which still has some unfortunate implications, like needing to interpret at runtime).


I've picked a really silly example of a DSL just to illustrate the point in a few lines, but I feel the silliness is obscuring what I wanted to communicate. Next time I'll try to come up with something more useful.

> macros introduce DSL in form of normal s-expression, but they don't actually behave like a function; macros introduce their own mini-language/syntax*

That's the point. S-expressions are structure notation language. The semantics of code expressed as s-expression is something else. There's the "default" one (as provided by #'eval), but macros allow you to work on the s-expressions as data structures. Ultimately, the macro expansion is still evaluated normally, but the expansion might be wildly different from the macro invocation.

This is a feature, not a bug. It gives you the power to add new abstractions to the language, as if they were part of that language in the first place. It's not something you need often, but there are things you can't do any other way. For example, since we're talking JavaScript - think of JSX. In JavaScript, it's a mind-bending innovation, though committing you to use a big code generation tool (Babel). In Lisp, you can do half of it with a macro[0].

A common use of macros is removing conceptual repetition in code. Imagine you have a concept in your codebase - say, a plugin. Creating a plugin involves defining a class extending a common base class, defining a bunch of methods that are identical in 90% of the cases, and a bunch of free functions. Conceptually, that whole ensemble is "a plugin". Lisp macros let you define that concept in code, and reduce your plugin definitions to just:

  (define-plugin some-name
    :some-specific-method (lambda () ...))
> In the last example you provided, I bet the macro implementation would look like a little interpreter?

Such macros are more like compilers. Interpreters execute the code they read; compilers - like those macro - emit different code instead.

> might be able to achieve the same behavior, right?

Yes, except the macro does that at expansion time - i.e. ahead of execution. In practice, this is almost always "compilation time".

> Just most of the time, I find functions are sufficient enough.

Because they are! Even in Lisp, macros are not your default tool for solving problems. Functions are. Macros come out when the best way to do something involves code that writes code for you.

--

[0] - And the other half with a reader macro. Regular macros transform trees before they're evaluated. Reader macros alter the way text is deserialized into trees. Reader macros are very rarely used, because they're a bit hard to keep contained and tend to screw with editors, but if you really want to create a different syntax for your code, they're there for you.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: