12 ms·
Yay! The birth of a language is a beautiful thing. I’m curious about the macros: how are these implemented? They seem like pretty straightforward unhygienic Li
by ashton314 2y ago
Yay! The birth of a language is a beautiful thing.
I’m curious about the macros: how are these implemented? They seem like pretty straightforward unhygienic Lisp macros, which is a little bit of a disappointment, but better some macros than none at all! Anything about the macro system that distinguishes it from the Common Lisp system? E.g. anything borrowed from Scheme or Racket? Docs are sparse here.
- kstrauser 2y agoIt’s far from new. In 2012 I worked for a shop who used an internal package named “hy”, and the introduction of this Hy made our builds break in a novel and interesting way. (Also, use something to insure your own internal packages have a higher priority, alright? That’s a lesson I didn’t need to learn twice.)
- ashton314 2y agoYou're right—my bad. I'm sad I hadn't heard about Hy sooner! Update then: The first stable release of a language is a beautiful thing! :)
- Kodiologist 2y agoSparse? I got a whole chapter for ya: https://hylang.org/hy/doc/v1.0.0/macros https://hylang.org/hy/doc/v1.0.0/macros
- ashton314 2y agoYes, and it's a very nice tutorial! I'm interested in implementation details. Maybe there's no hygiene (and no scope sets etc.) to worry about—that would probably make documentation a little shorter. I'm sure the documentation will grow as people run into edge cases. (I'm also probably a little spoiled with documentation coming from Racket which has like 4 big chapters dedicated to different aspects of macros scattered around the docs, plus some associated papers. Forgive me—I'm not trying to dunk on Hy; I just like reading docs.)
- Kodiologist 2y agoAdmittedly, I've tried not to document the implementation. Yeah, they're pretty much simple dirty Common Lisp macros. Internally, they're functions that are called with the arguments converted to models (via `hy.as-model`), and then the return value is converted to a model. If a macro's first parameter is named `_hy_compiler`, it gets access to the current compiler object; this is undocumented since it's only meant for internal use. Reader macros have no parameters, but can access the current reader object as `&reader`. When it's defined, a reader macro is added to the current reader's dispatch table.
- codr7 2y agoThere's nothing wrong with CL macros. Quite the opposite, they are more powerful than the alternatives. Macros are power tools, dumbing them down for safety is missing the point.
- ashton314 2y agoI have a hard time trusting the CL macros I write because of unexpected interactions with the context that I use them in. While it is the case that CL macros are more powerful than the R6RS macros-by-example system, Racket’s system (and some other newer languages that have adopted things pioneered by Scheme and Racket, such as Elixir) give you hygienic macros without sacrificing expressive power. I want my macros to be easy to write correctly. That can only happen when the system has proper hygiene.
- codr7 2y agoThey are not unexpected though. If you put your own symbols into generated code you better have a damn good idea what you're doing. It's a power tool.
- ashton314 2y agoTable saws were only improved by the addition of an emergency stop to prevent people from maiming themselves. Power tools don’t have to be dangerous. If you are wanting to introduce variable capture you better be really explicit about when you want it. If there’s no hygiene, I have to know everything about how the macro is implemented in order to trust it and use it confidently. Might be fine for small shorthand, but that won’t scale. You need non-leaky abstractions to build on them. Racket’s `syntax-parse` and “syntax parameters” show that you can have it both ways: procedural macros that are hygienic by default, but with an explicit escape hatch when you do want to introduce new bindings into the macro call site. It also gives you much much better errors. CL macros are about as dangerous as malloc/free, but without years of experience and tools like Valgrind to debug. They’re hard to trust and get right. Racket macros are like GC/affine typing: everything is correct by construction.