3 ms·
The syntactic approach subsumes the more semantic approach where the graph structure is made explicit. So, yeah, you can "compile" list structures to the bindin
by tel 7y ago
The syntactic approach subsumes the more semantic approach where the graph structure is made explicit. So, yeah, you can "compile" list structures to the binding graph and indeed you must.
Having more granular distinctions always helps in that it's easy to "forget" how things are different. It's also more primitive in that you have to actually do that step. It also leads to opportunities to do "wrong" things like anaphoric macros.
This is essentially a tradeoff where more power is offered to the author of the macro and less to the reader.
To make another comparison, we can take it one step further: a macro preprocessor which had access to the actual character stream can elect to do things not possible in lisp macros—e.g., distinguish on indentation or something to that effect—but also can recover all of the lisp macro techniques by merely parsing the character stream.
---
The heart of all of this, popping the stack up to my original comment, is that for lots of macros you don't really need to care at all about binding structure—or at least only minimally—and thus you can get lots of practical work done doing "just" syntactic transforms.
Once you are really working over a complex call graph—which is common in more complex DSLs like probabilistic programming languages—then CPS becomes really important as you want a way to split call graphs into pieces and a practical way of doing that is (value + continuation).
Worth noting, CPS transformations are a popular technique in more sophisticated lispy macro transforms, too.
- neilv 7y agoBTW, Racket syntax transformations work with Racket syntax objects [1], which is one way to do the indentation sensitivity you mention. Racket also has something called `#lang` for conveniently using arbitrary parsers, and a way to embed use of arbitrary readers for chunks of code within normal Racket code. [1] https://docs.racket-lang.org/reference/stxops.html https://docs.racket-lang.org/reference/stxops.html
- TeMPOraL 7y ago> a macro preprocessor which had access to the actual character stream can elect to do things not possible in lisp macros—e.g., distinguish on indentation or something to that effect—but also can recover all of the lisp macro techniques by merely parsing the character stream. Common Lisp has the mechanism called "reader macros" that can do that. It's a separate mechanism, because it works at "read time", which is much earlier than the "macroexpansion time" when the regular macros are processed.
- tel 7y agoYep, "macros" can operate at any point during the compilation/interpretation process to transform the inputs. Generally speaking, the earlier on the more simplistic the structures and the less inferential products available. Also, the greater flexibility and power. Later on, early stages of compilation/interpretation will strip away information, simplify products, add inferential information, etc. These pieces can be made available to macro systems staged later on. Lisp's most famous macros exist somewhat early in the compilation process, where trees have been parsed but variables aren't interpreted and the data structures are still simple.