Remix.run Logo
klibertp 4 hours ago

I don't think that moving the evaluation to compile time is something you can just ignore when discussing macros. It's an important differentiator between macros and Fexprs[1].

IME, the primary use case for macros in Lisps is language extension, a step before a DSL. For every `loop` there are thousands of `with-x` macro implementations. See the macro-writing macros in Alexandria/Serapeum for the most common patterns.

Also, some dynamic languages (Io, Prolog, Groovy) support DSLs through non-macro mechanisms. DSLs in those languages are as easy (or easier) to implement as in Lisps; however, they tend to be less performant. So, again, compile-time macro execution does matter for the DSL use case, too.

[1] https://en.wikipedia.org/wiki/Fexpr

ux266478 3 hours ago | parent | next [-]

In the case of Prolog, term and goal expansion are arbitrary compile-time execution mechanisms, completely isomorphic with macros, and are referred to as macro mechanisms.

The characterization of it not being "compile-time macro execution" is strange, what do you think these predicates are doing?

klibertp 3 hours ago | parent [-]

Good point. I was thinking about meta-interpreters (and it's still possible I misunderstood or misremembered how they work!), but you're right; I should have at least been more precise.

carlosneves 2 hours ago | parent | prev [-]

Thanks for linking to Fexpr's. I've thinking about "functions with lazily evaluated arguments" recently, and trying to understand how they are different from macros. So I was basically thinking about fexprs.

I have some reading to do, but overall it seems like macros are favored instead of fexprs. Macros completely avoid some environment handling issues.