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

From: Alex <[email-masked]>
Date: Fri, 09 Dec 2016 22:29:36 -0600

Alex <[email-masked]> writes:

> Compare the following:
>
> (let ((x 5)
>       (x 6))
>   (+ x 10))
>
> => 16
>
> (cl-letf ((x 5)
>           (x 6))
>   (+ x 10))
>
> => 15
>
>
> This also occurs when using non-trivial places:
>
> (setq v (vector 1 2 3 4 5))
>
> (cl-letf (((aref v 1) 10)
>           ((aref v 1) 20))
>   (aref v 1))
>
> => 10
>
>
> I ran into this when using two different setters that sometimes
> indirectly modify the same variable. The current behaviour makes the
> result of that unexpected.

I attached a patch that fixes this issue:

>From 9a74f1e7f8d8cc77b111473f8ee53e46af8a9957 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <[email-masked]>
Date: Fri, 9 Dec 2016 22:10:54 -0600
Subject: [PATCH] Preserve the order of bindings in cl--letf

Do not reverse the order of the bindings in cl-letf (Bug #25154).

* lisp/emacs-lisp/cl-macs.el (cl--letf): Use nreverse to restore the
  order of bindings.
---
 lisp/emacs-lisp/cl-macs.el | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 210a208..34f124f 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2388,7 +2388,10 @@ cl--letf
   ;;    VAL1; VAL2; PLACE1; bind1; PLACE2; bind2
   ;; Common-Lisp's `psetf' does the first, so we'll do the same.
   (if (null bindings)
-      (if (and (null binds) (null simplebinds)) (macroexp-progn body)
+      (if (and (null binds) (null simplebinds))
+          (macroexp-progn body)
+        (setq binds (nreverse binds))
+        (setq simplebinds (nreverse simplebinds))
         `(let* (,@(mapcar (lambda (x)
                             (pcase-let ((`(,vold ,getter ,_setter ,_vnew) x))
                               (list vold getter)))
-- 
2.10.2