unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#25154: 25.1; Bindings in cl-letf are in reverse order
@ 2016-12-09 23:36 Alex
  2016-12-10  4:29 ` Alex
  2016-12-10  7:22 ` Eli Zaretskii
  0 siblings, 2 replies; 17+ messages in thread
From: Alex @ 2016-12-09 23:36 UTC (permalink / raw)
  To: 25154

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.






^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-09 23:36 bug#25154: 25.1; Bindings in cl-letf are in reverse order Alex
@ 2016-12-10  4:29 ` Alex
  2016-12-10  7:22 ` Eli Zaretskii
  1 sibling, 0 replies; 17+ messages in thread
From: Alex @ 2016-12-10  4:29 UTC (permalink / raw)
  To: 25154

[-- Attachment #1: Type: text/plain, Size: 563 bytes --]

Alex <agrambot@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:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-letf patch --]
[-- Type: text/x-patch, Size: 1223 bytes --]

From 9a74f1e7f8d8cc77b111473f8ee53e46af8a9957 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-09 23:36 bug#25154: 25.1; Bindings in cl-letf are in reverse order Alex
  2016-12-10  4:29 ` Alex
@ 2016-12-10  7:22 ` Eli Zaretskii
  2016-12-10  7:43   ` Tino Calancha
  2016-12-10 18:05   ` Alex
  1 sibling, 2 replies; 17+ messages in thread
From: Eli Zaretskii @ 2016-12-10  7:22 UTC (permalink / raw)
  To: Alex; +Cc: 25154

> From: Alex <agrambot@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*'.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10  7:22 ` Eli Zaretskii
@ 2016-12-10  7:43   ` Tino Calancha
  2016-12-10 13:41     ` Philipp Stephani
  2016-12-10 18:05   ` Alex
  1 sibling, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2016-12-10  7:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25154, Alex, tino.calancha

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Alex <agrambot@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.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10  7:43   ` Tino Calancha
@ 2016-12-10 13:41     ` Philipp Stephani
  2016-12-10 14:01       ` Tino Calancha
  2016-12-10 14:09       ` Eli Zaretskii
  0 siblings, 2 replies; 17+ messages in thread
From: Philipp Stephani @ 2016-12-10 13:41 UTC (permalink / raw)
  To: Tino Calancha, Eli Zaretskii; +Cc: 25154, Alex

[-- Attachment #1: Type: text/plain, Size: 866 bytes --]

Tino Calancha <tino.calancha@gmail.com> schrieb am Sa., 10. Dez. 2016 um
08:45 Uhr:

> Eli Zaretskii <eliz@gnu.org> writes:
>
> >> From: Alex <agrambot@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.

[-- Attachment #2: Type: text/html, Size: 2008 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 13:41     ` Philipp Stephani
@ 2016-12-10 14:01       ` Tino Calancha
  2016-12-10 14:09       ` Eli Zaretskii
  1 sibling, 0 replies; 17+ messages in thread
From: Tino Calancha @ 2016-12-10 14:01 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: 25154, Alex, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 679 bytes --]



On Sat, 10 Dec 2016, Philipp Stephani wrote:

> 
> 
> Tino Calancha <tino.calancha@gmail.com> schrieb am Sa., 10. Dez. 2016 um 08:45 Uhr:
>       Eli Zaretskii <eliz@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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 13:41     ` Philipp Stephani
  2016-12-10 14:01       ` Tino Calancha
@ 2016-12-10 14:09       ` Eli Zaretskii
  2016-12-23 12:17         ` Philipp Stephani
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2016-12-10 14:09 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: 25154, agrambot, tino.calancha

> From: Philipp Stephani <p.stephani2@gmail.com>
> Date: Sat, 10 Dec 2016 13:41:16 +0000
> Cc: 25154@debbugs.gnu.org, Alex <agrambot@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.)





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10  7:22 ` Eli Zaretskii
  2016-12-10  7:43   ` Tino Calancha
@ 2016-12-10 18:05   ` Alex
  2016-12-10 18:14     ` npostavs
  2016-12-10 18:27     ` Eli Zaretskii
  1 sibling, 2 replies; 17+ messages in thread
From: Alex @ 2016-12-10 18:05 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25154

[-- Attachment #1: Type: text/plain, Size: 1789 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Alex <agrambot@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)))



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-letf patch reworded --]
[-- Type: text/x-diff, Size: 1251 bytes --]

From 184fa8dcb738923994d4b287931849b182bdb522 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 18:05   ` Alex
@ 2016-12-10 18:14     ` npostavs
  2016-12-10 19:41       ` Alex
  2016-12-10 18:27     ` Eli Zaretskii
  1 sibling, 1 reply; 17+ messages in thread
From: npostavs @ 2016-12-10 18:14 UTC (permalink / raw)
  To: Alex; +Cc: 25154

Alex <agrambot@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)





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 18:05   ` Alex
  2016-12-10 18:14     ` npostavs
@ 2016-12-10 18:27     ` Eli Zaretskii
  2016-12-10 19:52       ` Alex
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2016-12-10 18:27 UTC (permalink / raw)
  To: Alex; +Cc: 25154

> From: Alex <agrambot@gmail.com>
> Cc: 25154@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.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 18:14     ` npostavs
@ 2016-12-10 19:41       ` Alex
  0 siblings, 0 replies; 17+ messages in thread
From: Alex @ 2016-12-10 19:41 UTC (permalink / raw)
  To: npostavs; +Cc: 25154

npostavs@users.sourceforge.net writes:

> Alex <agrambot@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))





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 18:27     ` Eli Zaretskii
@ 2016-12-10 19:52       ` Alex
  2016-12-11  3:11         ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Alex @ 2016-12-10 19:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25154

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Alex <agrambot@gmail.com>
>> Cc: 25154@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.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 19:52       ` Alex
@ 2016-12-11  3:11         ` Tino Calancha
  0 siblings, 0 replies; 17+ messages in thread
From: Tino Calancha @ 2016-12-11  3:11 UTC (permalink / raw)
  To: Alex; +Cc: npostavs, 25154, Philipp Stephani, tino.calancha


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





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-10 14:09       ` Eli Zaretskii
@ 2016-12-23 12:17         ` Philipp Stephani
  2016-12-23 12:46           ` Tino Calancha
  2016-12-23 13:53           ` Eli Zaretskii
  0 siblings, 2 replies; 17+ messages in thread
From: Philipp Stephani @ 2016-12-23 12:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25154, agrambot, tino.calancha


[-- Attachment #1.1: Type: text/plain, Size: 923 bytes --]

Eli Zaretskii <eliz@gnu.org> schrieb am Sa., 10. Dez. 2016 um 15:09 Uhr:

> > From: Philipp Stephani <p.stephani2@gmail.com>
> > Date: Sat, 10 Dec 2016 13:41:16 +0000
> > Cc: 25154@debbugs.gnu.org, Alex <agrambot@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.

[-- Attachment #1.2: Type: text/html, Size: 1810 bytes --]

[-- Attachment #2: 0001-Document-that-variable-binding-order-is-unspecified.txt --]
[-- Type: text/plain, Size: 1796 bytes --]

From 42d7450c41d69a713eb8f9492cc169e8c2bc15ca Mon Sep 17 00:00:00 2001
From: Philipp Stephani <phst@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@dots{}) forms@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.
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-23 12:17         ` Philipp Stephani
@ 2016-12-23 12:46           ` Tino Calancha
  2016-12-23 13:53           ` Eli Zaretskii
  1 sibling, 0 replies; 17+ messages in thread
From: Tino Calancha @ 2016-12-23 12:46 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: 25154, agrambot, tino.calancha

Philipp Stephani <p.stephani2@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@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@dots{}) forms@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





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-23 12:17         ` Philipp Stephani
  2016-12-23 12:46           ` Tino Calancha
@ 2016-12-23 13:53           ` Eli Zaretskii
  2016-12-23 16:30             ` Philipp Stephani
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2016-12-23 13:53 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: 25154, agrambot, tino.calancha

> From: Philipp Stephani <p.stephani2@gmail.com>
> Date: Fri, 23 Dec 2016 12:17:54 +0000
> Cc: tino.calancha@gmail.com, 25154@debbugs.gnu.org, agrambot@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".





^ permalink raw reply	[flat|nested] 17+ messages in thread

* bug#25154: 25.1; Bindings in cl-letf are in reverse order
  2016-12-23 13:53           ` Eli Zaretskii
@ 2016-12-23 16:30             ` Philipp Stephani
  0 siblings, 0 replies; 17+ messages in thread
From: Philipp Stephani @ 2016-12-23 16:30 UTC (permalink / raw)
  To: Eli Zaretskii, 25154-done; +Cc: agrambot, tino.calancha

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

Eli Zaretskii <eliz@gnu.org> schrieb am Fr., 23. Dez. 2016 um 14:53 Uhr:

> > From: Philipp Stephani <p.stephani2@gmail.com>
> > Date: Fri, 23 Dec 2016 12:17:54 +0000
> > Cc: tino.calancha@gmail.com, 25154@debbugs.gnu.org, agrambot@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.

[-- Attachment #2: Type: text/html, Size: 1562 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-12-23 16:30 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-09 23:36 bug#25154: 25.1; Bindings in cl-letf are in reverse order Alex
2016-12-10  4:29 ` Alex
2016-12-10  7:22 ` Eli Zaretskii
2016-12-10  7:43   ` Tino Calancha
2016-12-10 13:41     ` Philipp Stephani
2016-12-10 14:01       ` Tino Calancha
2016-12-10 14:09       ` Eli Zaretskii
2016-12-23 12:17         ` Philipp Stephani
2016-12-23 12:46           ` Tino Calancha
2016-12-23 13:53           ` Eli Zaretskii
2016-12-23 16:30             ` Philipp Stephani
2016-12-10 18:05   ` Alex
2016-12-10 18:14     ` npostavs
2016-12-10 19:41       ` Alex
2016-12-10 18:27     ` Eli Zaretskii
2016-12-10 19:52       ` Alex
2016-12-11  3:11         ` Tino Calancha

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).