Subject: bug#25154: 25.1; Bindings in cl-letf are in reverse order

From: Alex <[email-masked]>
Date: Sat, 10 Dec 2016 13:52:34 -0600

Eli Zaretskii <[email-masked]> writes:

>> From: Alex <[email-masked]>
>> Cc: [email-masked]
>> Date: Sat, 10 Dec 2016 12:05:40 -0600
>> 
>> > Isn't it true that the order of evaluation in a 'let' is unspecified?
>> > If you want a particular order, use 'let*'.
>> 
>> I don't think so. See (info "(elisp) Local Variables"):
>> 
>>   All of the VALUE-FORMs in BINDINGS are evaluated in the order they
>>   appear
>
> That's the evaluation order.

Yes, which is what the (nreverse binds) in my patch actually affects,
despite the name of the variable being `binds'. This is why I said that
my choice of wording for this bug report was wrong, as it focused on a
less important problem.

As said in my last email, the expression:

(cl-letf (((aref v 1) 10)
          ((aref w 2) 20))
  (aref v 1))

expands to:

(let*
    ((v v)
     (v w)
     (old
      (aref v 2))
     (old
      (aref v 1)))
  (unwind-protect
      (progn
        (aset v 2 20)
        (aset v 1 10)
        (aref v 1))
    (aset v 2 old)
    (aset v 1 old)))

which does indeed evaluate the arefs and asets in reverse order. This is
the most important part of my patch.

> Your code relies on the order of
> _binding_ variables to values, which is unspecified.  Contrast the
> above with the description of 'let*' below it.

Just the (nreverse simplebinds) line, which I added just to make cl-letf
a little bit saner (i.e. more like let). This part does seem to be
unspecified, but I don't see why it should unnecessarily diverge from
let.