GNU bug report logs - #25154
25.1; Bindings in cl-letf are in reverse order

Previous Next

Package: emacs;

Reported by: Alex <agrambot <at> gmail.com>

Date: Fri, 9 Dec 2016 23:55:02 UTC

Severity: minor

Tags: notabug

Found in version 25.1

Done: Philipp Stephani <p.stephani2 <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 25154 in the body.
You can then email your comments to 25154 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Fri, 09 Dec 2016 23:55:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Alex <agrambot <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 09 Dec 2016 23:55:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Alex <agrambot <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 09 Dec 2016 17:36:15 -0600
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.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 04:30:02 GMT) Full text and rfc822 format available.

Message #8 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Alex <agrambot <at> gmail.com>
To: 25154 <at> debbugs.gnu.org
Subject: Re: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 09 Dec 2016 22:29:36 -0600
[Message part 1 (text/plain, inline)]
Alex <agrambot <at> gmail.com> 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:

[0001-Preserve-the-order-of-bindings-in-cl-letf.patch (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 07:22:02 GMT) Full text and rfc822 format available.

Message #11 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Alex <agrambot <at> gmail.com>
Cc: 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 09:22:15 +0200
> From: Alex <agrambot <at> gmail.com>
> Date: Fri, 09 Dec 2016 17:36:15 -0600
> 
> Compare the following:
> 
> (let ((x 5)
>       (x 6))
>   (+ x 10))
> 
> => 16
> 
> (cl-letf ((x 5)
>           (x 6))
>   (+ x 10))
> 
> => 15

Isn't it true that the order of evaluation in a 'let' is unspecified?
If you want a particular order, use 'let*'.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 07:44:02 GMT) Full text and rfc822 format available.

Message #14 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 25154 <at> debbugs.gnu.org, Alex <agrambot <at> gmail.com>, tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 16:43:02 +0900
Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Alex <agrambot <at> gmail.com>
>> Date: Fri, 09 Dec 2016 17:36:15 -0600
>> 
>> Compare the following:
>> 
>> (let ((x 5)
>>       (x 6))
>>   (+ x 10))
>> 
>> => 16
>> 
>> (cl-letf ((x 5)
>>           (x 6))
>>   (+ x 10))
>> 
>> => 15
>
> Isn't it true that the order of evaluation in a 'let' is unspecified?
> If you want a particular order, use 'let*'.
Right, the order of evaluation in a let is up to the implementation.  A program
should not rely on such details.
The same statement should apply to cl-letf.




Added tag(s) notabug. Request was from Tino Calancha <tino.calancha <at> gmail.com> to control <at> debbugs.gnu.org. (Sat, 10 Dec 2016 07:44:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 13:42:01 GMT) Full text and rfc822 format available.

Message #19 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Philipp Stephani <p.stephani2 <at> gmail.com>
To: Tino Calancha <tino.calancha <at> gmail.com>, Eli Zaretskii <eliz <at> gnu.org>
Cc: 25154 <at> debbugs.gnu.org, Alex <agrambot <at> gmail.com>
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 13:41:16 +0000
[Message part 1 (text/plain, inline)]
Tino Calancha <tino.calancha <at> gmail.com> schrieb am Sa., 10. Dez. 2016 um
08:45 Uhr:

> Eli Zaretskii <eliz <at> gnu.org> writes:
>
> >> From: Alex <agrambot <at> gmail.com>
> >> Date: Fri, 09 Dec 2016 17:36:15 -0600
> >>
> >> Compare the following:
> >>
> >> (let ((x 5)
> >>       (x 6))
> >>   (+ x 10))
> >>
> >> => 16
> >>
> >> (cl-letf ((x 5)
> >>           (x 6))
> >>   (+ x 10))
> >>
> >> => 15
> >
> > Isn't it true that the order of evaluation in a 'let' is unspecified?
> > If you want a particular order, use 'let*'.
> Right, the order of evaluation in a let is up to the implementation.  A
> program
> should not rely on such details.
> The same statement should apply to cl-letf.
>
>
>
>
I think that should be mentioned explicitly in the manuals: given that the
order of value evaluations is specified, people might expect the same for
the bindings themselves.
[Message part 2 (text/html, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 14:03:02 GMT) Full text and rfc822 format available.

Message #22 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Philipp Stephani <p.stephani2 <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 25154 <at> debbugs.gnu.org,
 Alex <agrambot <at> gmail.com>, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 23:01:55 +0900 (JST)
[Message part 1 (text/plain, inline)]

On Sat, 10 Dec 2016, Philipp Stephani wrote:

> 
> 
> Tino Calancha <tino.calancha <at> gmail.com> schrieb am Sa., 10. Dez. 2016 um 08:45 Uhr:
>       Eli Zaretskii <eliz <at> gnu.org> writes:
>
>       Right, the order of evaluation in a let is up to the implementation.  A program
>       should not rely on such details.
>       The same statement should apply to cl-letf.
Sorry, i meant above
the order of 'assign the bindings' is up to the implementation.

> I think that should be mentioned explicitly in the manuals: given that the order of value evaluations is specified, people might
> expect the same for the bindings themselves.
Yes, it's worth to remark than in the manual.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 14:10:01 GMT) Full text and rfc822 format available.

Message #25 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Philipp Stephani <p.stephani2 <at> gmail.com>
Cc: 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com, tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 16:09:45 +0200
> From: Philipp Stephani <p.stephani2 <at> gmail.com>
> Date: Sat, 10 Dec 2016 13:41:16 +0000
> Cc: 25154 <at> debbugs.gnu.org, Alex <agrambot <at> gmail.com>
> 
>  > Isn't it true that the order of evaluation in a 'let' is unspecified?
>  > If you want a particular order, use 'let*'.
>  Right, the order of evaluation in a let is up to the implementation. A program
>  should not rely on such details.
>  The same statement should apply to cl-letf.
> 
> I think that should be mentioned explicitly in the manuals: given that the order of value evaluations is specified,
> people might expect the same for the bindings themselves.

I agree, patches to that effect are welcome.  (AFAICT, the manual
tries to say that already, but the wording could be more explicit.)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 18:06:01 GMT) Full text and rfc822 format available.

Message #28 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Alex <agrambot <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 12:05:40 -0600
[Message part 1 (text/plain, inline)]
Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Alex <agrambot <at> gmail.com>
>> Date: Fri, 09 Dec 2016 17:36:15 -0600
>> 
>> Compare the following:
>> 
>> (let ((x 5)
>>       (x 6))
>>   (+ x 10))
>> 
>> => 16
>> 
>> (cl-letf ((x 5)
>>           (x 6))
>>   (+ x 10))
>> 
>> => 15
>
> 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.

Though I realize that I have made a mistake in naming this bug and
patch. The bigger issue is that all (PLACE VALUE) pairs of each type
(simple and more importantly complex) were being evaluated in reverse
order. Take for example:

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


This approximately 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)))

As you can see, the arefs and asets are evaluated in reverse order.
Again, even if you argue that the order of evaluation for (PLACE VALUE)
pairs is unspecified, it's evaluating them in an unexpected way for no
good reason.

I have attached a reworded patch that expands the above into the more
expected:

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


[0001-Preserve-the-order-of-PLACE-VALUE-pairs-in-cl-letf.patch (text/x-diff, inline)]
From 184fa8dcb738923994d4b287931849b182bdb522 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot <at> gmail.com>
Date: Fri, 9 Dec 2016 22:10:54 -0600
Subject: [PATCH] Preserve the order of (PLACE VALUE) pairs in cl-letf

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

* lisp/emacs-lisp/cl-macs.el (cl--letf): Use nreverse to restore the
  order of (PLACE VALUE) pairs.
---
 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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 18:14:01 GMT) Full text and rfc822 format available.

Message #31 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: npostavs <at> users.sourceforge.net
To: Alex <agrambot <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 13:14:54 -0500
Alex <agrambot <at> gmail.com> 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)

Although `let' does happen to perform the bindings in order too.

(let ((x 0))
  (let ((a (setq x 1))
        (a (setq x 2)))
    (list x a))) ;=> (2 2)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 18:28:02 GMT) Full text and rfc822 format available.

Message #34 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Alex <agrambot <at> gmail.com>
Cc: 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 20:27:40 +0200
> From: Alex <agrambot <at> gmail.com>
> Cc: 25154 <at> debbugs.gnu.org
> 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.  Your code relies on the order of
_binding_ variables to values, which is unspecified.  Contrast the
above with the description of 'let*' below it.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 19:42:02 GMT) Full text and rfc822 format available.

Message #37 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Alex <agrambot <at> gmail.com>
To: npostavs <at> users.sourceforge.net
Cc: Eli Zaretskii <eliz <at> gnu.org>, 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 13:41:04 -0600
npostavs <at> users.sourceforge.net writes:

> Alex <agrambot <at> gmail.com> 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))




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sat, 10 Dec 2016 19:53:01 GMT) Full text and rfc822 format available.

Message #40 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Alex <agrambot <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 25154 <at> debbugs.gnu.org
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sat, 10 Dec 2016 13:52:34 -0600
Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Alex <agrambot <at> gmail.com>
>> Cc: 25154 <at> debbugs.gnu.org
>> 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.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Sun, 11 Dec 2016 03:12:01 GMT) Full text and rfc822 format available.

Message #43 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Alex <agrambot <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, tino.calancha <at> gmail.com,
 25154 <at> debbugs.gnu.org, Philipp Stephani <p.stephani2 <at> gmail.com>,
 npostavs <at> users.sourceforge.net
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Sun, 11 Dec 2016 12:11:16 +0900
Hi Alex,

thank you for your report and your time!
I answer you below.

>> 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
Eli means here "order on the bindings assignment is unspecified in a 'let'".
Programs shouldn't rely on any particular order in the assigments: it's an
implementation detail.

>This approximately 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)))
>
>As you can see, the arefs and asets are evaluated in reverse order.
>Again, even if you argue that the order of evaluation for (PLACE VALUE)
>pairs is unspecified, it's evaluating them in an unexpected way for no
>good reason.
There is a good reason: the result code implementing cl-letf is simpler.
Your patch unnecessarily adds calls to `setq' and `nreverse'.  That result
in longer code and less efficient.
Bear in mind that `let' and `cl-letf' are written in different languages;
the former in C, the latter in elisp.  As far as those implementations
satisfy their specification, the simpler and more efficient that they
can be the better.

>> 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))
No it doesn't matter, because as pointed out above the order to perform the
parallel bindings is unspecified.  It might start binding from left to right,
or right to left, or even random order using the current time as a seed.
Code relying in a particular order for those bindings is not portable, even more,
it has a bug; we might change the implemention in the future for whatever
reason producing a different order: then such code will break.

If you want the bindings being perform from left to right, then you just need
to use sequential `letf*'/`cl-letf*' instead of the parallel `let'/`cl-letf'.

>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.
In addition to result in a simpler implementation, it's useful as a reminder
that code shouldn't assume a particular order.

Even if i don't see any problem with `cl-letf' implementation, i agree with
Philipp and Eli that it would be worth if the outcome of this report is an improvement
in the documentation.  We might update the manual adding a more precise statement
to clarify that the order to perform the parallel bindings is unspecified, i.e.,
code should not assume a particular order.
As Eli said patches are welcome.
Alex, are you willing to prepare those doc patches?

Thank you very much,
Tino




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Fri, 23 Dec 2016 12:19:01 GMT) Full text and rfc822 format available.

Message #46 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Philipp Stephani <p.stephani2 <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com, tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 23 Dec 2016 12:17:54 +0000
[Message part 1 (text/plain, inline)]
Eli Zaretskii <eliz <at> gnu.org> schrieb am Sa., 10. Dez. 2016 um 15:09 Uhr:

> > From: Philipp Stephani <p.stephani2 <at> gmail.com>
> > Date: Sat, 10 Dec 2016 13:41:16 +0000
> > Cc: 25154 <at> debbugs.gnu.org, Alex <agrambot <at> gmail.com>
> >
> >  > Isn't it true that the order of evaluation in a 'let' is unspecified?
> >  > If you want a particular order, use 'let*'.
> >  Right, the order of evaluation in a let is up to the implementation. A
> program
> >  should not rely on such details.
> >  The same statement should apply to cl-letf.
> >
> > I think that should be mentioned explicitly in the manuals: given that
> the order of value evaluations is specified,
> > people might expect the same for the bindings themselves.
>
> I agree, patches to that effect are welcome.  (AFAICT, the manual
> tries to say that already, but the wording could be more explicit.)
>

OK, I've attached a patch that hopefully clarifies this a bit.
[Message part 2 (text/html, inline)]
[0001-Document-that-variable-binding-order-is-unspecified.txt (text/plain, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Fri, 23 Dec 2016 12:47:02 GMT) Full text and rfc822 format available.

Message #49 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Philipp Stephani <p.stephani2 <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com,
 tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 23 Dec 2016 21:46:39 +0900
Philipp Stephani <p.stephani2 <at> gmail.com> writes:

>  I agree, patches to that effect are welcome.  (AFAICT, the manual
>  tries to say that already, but the wording could be more explicit.)
>
> OK, I've attached a patch that hopefully clarifies this a bit. 
>
> From 42d7450c41d69a713eb8f9492cc169e8c2bc15ca Mon Sep 17 00:00:00 2001
> From: Philipp Stephani <phst <at> google.com>
> Date: Fri, 23 Dec 2016 13:14:55 +0100
> Subject: [PATCH] Document that variable binding order is unspecified
>
> * doc/lispref/variables.texi (Local Variables):
> * cl.texi (Modify Macros): Document that assignment order in 'let' and
> 'cl-letf' is unspecified.
> ---
>  doc/lispref/variables.texi | 12 ++++++++++++
>  doc/misc/cl.texi           |  5 +++++
>  2 files changed, 17 insertions(+)
>
> diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
> index a2d64815d9..e2c8c542ab 100644
> --- a/doc/lispref/variables.texi
> +++ b/doc/lispref/variables.texi
> @@ -221,6 +221,18 @@ Local Variables
>       @result{} (1 2)
>  @end group
>  @end example
> +
> +On the other hand, the order of @emph{assignments} is unspecified: in
> +the following example, either 1 or 2 might be printed.
> +
> +@example
> +(let ((x 1)
> +      (x 2))
> +  (print x))
> +@end example
> +
> +Therefore, avoid binding a variable more than once in a single
> +@code{let} form.
>  @end defspec
>  
>  @defspec let* (bindings <at> dots{}) forms <at> dots{}
> diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
> index c62fa727c1..aa047e2122 100644
> --- a/doc/misc/cl.texi
> +++ b/doc/misc/cl.texi
> @@ -1179,6 +1179,11 @@ Modify Macros
>  as @code{setf} places; each will accept either an integer or a
>  marker as the stored value.)
>  
> +Like in the case of @code{let}, the @var{value} forms are evaluated in
> +the order they appear, but the order of assignments is unspecified.
> +Therefore, avoid assigning to the same @var{place} more than once in a
> +single @code{cl-letf} form.
> +
>  Since generalized variables look like lists, @code{let}'s shorthand
>  of using @samp{foo} for @samp{(foo nil)} as a @var{binding} would
>  be ambiguous in @code{cl-letf} and is not allowed.

It looks good to me.  Thank you.
Tino




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25154; Package emacs. (Fri, 23 Dec 2016 13:54:02 GMT) Full text and rfc822 format available.

Message #52 received at 25154 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Philipp Stephani <p.stephani2 <at> gmail.com>
Cc: 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com, tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 23 Dec 2016 15:53:05 +0200
> From: Philipp Stephani <p.stephani2 <at> gmail.com>
> Date: Fri, 23 Dec 2016 12:17:54 +0000
> Cc: tino.calancha <at> gmail.com, 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com
> 
>  I agree, patches to that effect are welcome. (AFAICT, the manual
>  tries to say that already, but the wording could be more explicit.)
> 
> OK, I've attached a patch that hopefully clarifies this a bit. 

Thanks.  My only comment is that I think we prefer talking about
"binding" instead of "assignment".




Reply sent to Philipp Stephani <p.stephani2 <at> gmail.com>:
You have taken responsibility. (Fri, 23 Dec 2016 16:32:02 GMT) Full text and rfc822 format available.

Notification sent to Alex <agrambot <at> gmail.com>:
bug acknowledged by developer. (Fri, 23 Dec 2016 16:32:02 GMT) Full text and rfc822 format available.

Message #57 received at 25154-done <at> debbugs.gnu.org (full text, mbox):

From: Philipp Stephani <p.stephani2 <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>, 25154-done <at> debbugs.gnu.org
Cc: agrambot <at> gmail.com, tino.calancha <at> gmail.com
Subject: Re: bug#25154: 25.1; Bindings in cl-letf are in reverse order
Date: Fri, 23 Dec 2016 16:30:47 +0000
[Message part 1 (text/plain, inline)]
Eli Zaretskii <eliz <at> gnu.org> schrieb am Fr., 23. Dez. 2016 um 14:53 Uhr:

> > From: Philipp Stephani <p.stephani2 <at> gmail.com>
> > Date: Fri, 23 Dec 2016 12:17:54 +0000
> > Cc: tino.calancha <at> gmail.com, 25154 <at> debbugs.gnu.org, agrambot <at> gmail.com
> >
> >  I agree, patches to that effect are welcome. (AFAICT, the manual
> >  tries to say that already, but the wording could be more explicit.)
> >
> > OK, I've attached a patch that hopefully clarifies this a bit.
>
> Thanks.  My only comment is that I think we prefer talking about
> "binding" instead of "assignment".
>

OK, replaced "assign" with "bind" and pushed to emacs-25 as
c04ac8a3191820d37e7858b7ca4e31cf04808cc3.
[Message part 2 (text/html, inline)]

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 21 Jan 2017 12:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 8 years and 150 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.