š¾ Archived View for idiomdrottning.org āŗ sloppy-tree-accessors captured on 2023-11-04 at 11:48:50. Gemini links have been rewritten to link to archived content
ā¬ ļø Previous capture (2023-01-29)
-=-=-=-=-=-=-
I learned Scheme before Common Lisp and Emacs Lisp (well, my very first exposure was to the very basics of Emacs Lisp, I didnāt even get to defun part), but Iāve done my fair share of Common Lisp since and Iāve been vindicated in one thing I kinda independently invented and Iām sure a lot of other impatient, lazy, and hubristic hacks came up with the same thing.
I often found myself wanting to do things on car, if there is a car. Or on cdr, if there is a cdr. And so on.
I called these accessors scar and scdr, and I at first thought ās for āsafeā since they wonāt error! I am so smart!ā but soon enough realized these were anything but safe, since they fail silently!
I started using them a little bit less, andā¦ veeery carefully. Guiltily and self-deprecatingly, I started thinking of the s as standing for Sandraās. When I made brev, which has an arbitrary-depth generator for them (you can (make-sloppy-tree-accessor scdaaddaaddadddadaaaadr) or whatever), I came up with the name āsloppyā and started feeling less bad.
All of this stems from '() and #f being two separate values in Scheme where Common Lisp and Emacs Lisp only has nil. So on there, you can (cadar ()) and it doesnāt bork. Vindicated!
I feel that with sloppy tree accessors carefully and judiciously applied, and eif (which treats empty as falsy) as an option next to the normal, safe if, we can have the best of both worlds. Convenience when we know what weāre doing, but retaining the ability to discriminate between these value types when we need to.
Elias wrote in, asking:
Being someone who definitely prefers CL, I wonder when you need to discriminate between them?
I love the convenience of CL in this particular regard.
Hereās my take: 90% of the time I donāt care. 8% I want the CL style. 2% of the time I do want them as separate.
One example is when you have a function that can return ``#f if it doesnāt find what itās looking for, or a list (including the empty list) if it does. Only way to do this on CL is with boxing (sorta like the Haskell āJust Maybeā ridiculousness).
alist-ref from Chickenās base module is an obvious example.
(aif (alist-ref foo bar) (frobnicate it) (not found so update the alist instead))
To get the CL behavior, thatās why I made eif which is an aif that does treat empty as falsy.
As an aside, those ā90% of the time when I donāt careā, it does find me some bugs, so. š¤·š»āāļø (Thatās also what all those straight-jacket typed languages fans keep writing in about when they hear that I love dynamic typing and hate the redundant human compiler at work annotating types and duplicating code. Even though brev has dependent types (albeit runtime, not compile time).)
But in CLās defense, half of those ābugsā wouldnāt even be bugs in CL. If Iām like
(if (eq foo (car bar)) this that)
then thatās just as good (on CL) and non-buggy (on CL) as the annoying, overly explicit Scheme style of
(if (and (pair? bar) (eq? foo (car bar))) this that)
Thatās what sloppy tree accessors fix:
(if (eq? foo (scar bar)) this that)
Brev. Making Scheme almost as good as CL since 2021 š¤¦š»āāļø