=> ↩ go back to index

Releasing Some New Common Lisp Macros

April 8, 2023

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?

=> [1]: Design by Contract | | [3]: install the system to your Quicklisp local projects | [4]: install the system where ASDF can find lisp-utils.asd | [5]: new let | | [7]: Lisping at JPL article

=> ↩ go back to index

=> also available on the web | and available on gopher

=> contact via email: alex [at] nytpu.com | or through anywhere else I'm at

=> backlinks

=> -- Copyright © 2023 nytpu - CC BY-SA 4.0

Proxy Information
Original URL
gemini://nytpu.com/gemlog/2023-04-08.gmi
Status Code
Success (20)
Meta
text/gemini;lang=en-US;charset=utf-8
Capsule Response Time
831.985384 milliseconds
Gemini-to-HTML Time
1.279754 milliseconds

This content has been proxied by September (3851b).