š¾ Archived View for nytpu.com āŗ gemlog āŗ 2023-04-08.gmi captured on 2023-09-08 at 16:07:38. Gemini links have been rewritten to link to archived content
ā¬ ļø Previous capture (2023-04-19)
ā”ļø Next capture (2024-06-20)
-=-=-=-=-=-=-
Last week or so I finally sat down and wrote my pretty ideal binding macro for Common Lispābasically a rite of passage for any Lisper given all the other ones I've stumbled across. I just fully rewrote it yesterday after using it in some real code and cleaning it up a bit; so I guess I should actually tell people about it in case anyone ends up interested in it since I really like it so far. Although like almost all of my projects it's written for me and I don't expect anyone else to end up using it (not necessarily a bad thing).
The `BIND` macro itself can be found at:
https://git.sr.ht/~nytpu/lisp-utils/tree/master/bind.lisp
I decided to bundle it up with a little Design by Contract[1] library that I wrote last year and ended up heavily using in Lasso[2]. It's in an uncreatively named ālisp-utilsā ASDF system:
https://git.sr.ht/~nytpu/lisp-utils
I don't have any specific plans to expand it out further, but I forsee adding more stuff if/when I write some cool general-purpose macro in the course of other programming. At any rate, I'm very firm on making every file/component in it entirely self-contained (including the DEFPACKAGEs) and with zero external dependencies, so you can just copy the file of interest into your project, install the system to your Quicklisp local projects[3] if you use that for dependency management, or otherwise install the system where ASDF can find lisp-utils.asd[4].
I heavily took inspiration from a few older binding macros, namely Scott L. Burson's new let[5] that was apparently originally written all the way back in 1980 (before Common Lisp existed!), and Ron Garret's BINDING-BLOCK[6], Ron Garrent being the author of the nice Lisping at JPL article[7]. I figured taking ideas from some very experienced and intelligent Lisp programmers, and then just morphing them into a syntax I like would be a good strategy. I think I succesfully captured the āflatteningā of deeply-nested bindings of BINDING-BLOCK (especially with my heavy use of multiple return values which otherwise gets super nested), while still keeping it less procedural and more LET-style like new let.
After using it in some real code that I'm working on, it confirmed my thought that most of the time I'd be using it as a drop-in replacement for LET/LET*, so I wanted to make sure that ārunsā of sequential bindings of the same type (currently LET-style bindinds and lambdas) are condensed into one single invocation of LET* or LABELS. This means that using BIND in place of LET* should have zero impact even without a decent optimizing implementation, since it expands into an identical single LET*. Even with more complex statements using the more fancy features, the number of forms is minimised wherever possible to where it *should* be no worse than writing the equivalent expression by hand. The worst is perhaps some superfluous use of LET* where LET could've been used instead, but a big part of yesterday's rewrite was making the bindings always sequential instead of trying to have a special separate sequential operator that made it annoying and verbose to use.
Overall I'm pretty happy with it so far, and I am still quite fond of that Design by Contract library so I'm glad I extracted it from Lasso into a standalone thing. Maybe check them out if you're interested?
[3]: install the system to your Quicklisp local projects
[4]: install the system where ASDF can find lisp-utils.asd
ā