Am Fr., 3. Juni 2022 um 15:10 Uhr schrieb siiky <xxxxxx@net-c.cat>:
Hey all,


I don't know of any convenient way to work with alist values, --
destructuring (by key) and binding values to variables -- that doesn't
involve manually

(let ((foo (alist-ref 'foo al))
       (bar (alist-ref 'bar al))
       (x (alist-ref 'zaz al))
       BINDING ...)
   ; Do something with foo, bar, x, ...
   BODY ...)

This, and any macro expanding in such a piece of code is not very efficient, i.e. O(n²) instead of the optimal O(n).

You would want to linearly scan the alist once and fill in the values of the variables during the scan.  A second scan over the value vector can than fill in defaults.

Few general pattern matchers will be able to generate optimal code in this regard, so you will have to program it by hand, I think.

That said, a general problem with an alist-let macro like the one you propose is that it confuses identifiers and symbols.  The keys of your alist are symbols while the variables are represented by identifiers that, for example, can be renamed ones through invocations of hygienic macros.

This can be solved in two ways:  The obvious way is that one has to write down the name of the identifier and the symbol, by which it has to be looked up in the alist, separately in the invocation of the alist-let macro.

Another way would be that the alist macro would not bind identifiers corresponding to keys directly but would, instead, bind a single identifier, say `:`, that can be used in conjunction with the keys to look up (in constant time) the value (or calculated default) corresponding to a symbol.

(alist-let al (foo bar (x zaz) BINDING ...)
   ; Do something with foo, bar, x, ...:
   (display (: foo))
   (frobnicate (: bar))
   (kill (: x))
   BODY ...)

Such an alist-let macro would bind `:` unhygienically (but in a controlled way).  If you don't want this, you have to sneak `:` in the macro invocation, e.g. as in the following invocation:

(alist-let al (: foo bar (x zaz) BINDING ...)
   ; Do something with foo, bar, x, ...:
   (display (: foo))
   (frobnicate (: bar))
   (kill (: x))
   BODY ...)

Marc