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

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

[email-masked] writes:

> Alex <[email-masked]> writes:
>
>>>
>>> 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
>>
>> I believe it should follow for cl-letf. Besides, even if it was
>> unspecified, evaluating in the order they appear would be adhering to
>> the principle of least astonishment.
>
> The value forms are evaluated in order, the bindings are not necessarily
> in order.
>
> (let ((x 0))
>   (cl-letf ((a (setq x 1))
>             (a (setq x 2)))
>     (list x a))) ;=> (2 1)

Right, this expands to:

(let ((x 0))
  (let*
      ((vnew
        (setq x 1))
       (vnew
        (setq x 2))
       (a vnew)
       (a vnew))
    (unwind-protect
        (list x a))))

Which, outside of the case of repeating the variable name (which
arguably shouldn't be allowed like in some other Lisps), doesn't matter.

It only matters when using more complex places like

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