• setq and places (was: Stupid beginner CL question)

    From Stefan Monnier@21:1/5 to All on Sun Jul 13 17:25:51 2025
    setf is a clever macro that can update a bunch of different types of
    mutable objects, rather than just symbol values.
    Yeah: `setq` is a special form to mutate a variable, whereas `setf` is
    a macro that can mutate any "place"

    But remember:
    "If any var refers to a binding made by symbol-macrolet, then that var
    is treated as if setf (not setq) had been used."

    https://www.lispworks.com/documentation/HyperSpec/Body/s_setq.htm

    Yeah, it makes `symbol-macrolet` more useful. but it's also kind of
    weird: in practice, it turns it into a kind of `let-place`, except that
    it doesn't benefit from the careful scoping and evaluation semantics
    of places. E.g.

    (symbol-macrolet ((x (aref (FOO) (BAR))))
    ... x ... (setq x (TOTO)) ...)

    will re-evaluate (FOO) and (BAR) for every use of `x`, and it does it by copying the code to the various occurrences of `x`, where each
    occurrence may end up suffering from name capture.

    FWIW, ELisp has `cl-symbol-macrolet` and does not have anything like
    a "let-place". The closest you can get is to use `gv-ref`, which is
    ELisp's equivalent to C's `&`, so you could do:

    (let ((x (gv-ref (aref (FOO) (BAR)))))
    ... (gv-deref x) ... (setf (gv-deref x) (TOTO)) ...)

    which does provide the "desired" semantics (e.g. `(FOO)` is evaluated
    only once and in its proper scope), but is implemented in a somewhat
    costly way (the `gv-ref` builds a pair of closures to get resp. set the
    value of the place).


    Stefan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Monnier@21:1/5 to All on Sun Jul 13 18:53:43 2025
    (symbol-macrolet ((x (aref (FOO) (BAR))))
    ^^
    '
    Duh!


    Stefan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)