GNU bug report logs - #17825
broken set! in iteration

Previous Next

Package: guile;

Reported by: Alírio Eyng <alirioeyng <at> gmail.com>

Date: Sat, 21 Jun 2014 02:55:02 UTC

Severity: normal

Tags: notabug

Done: Mark H Weaver <mhw <at> netris.org>

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 17825 in the body.
You can then email your comments to 17825 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-guile <at> gnu.org:
bug#17825; Package guile. (Sat, 21 Jun 2014 02:55:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Alírio Eyng <alirioeyng <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Sat, 21 Jun 2014 02:55:02 GMT) Full text and rfc822 format available.

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

From: Alírio Eyng <alirioeyng <at> gmail.com>
To: bug-guile <at> gnu.org
Subject: broken set! in iteration
Date: Sat, 21 Jun 2014 01:25:56 +0000
I can't see why the second code doesn't work like the first:

(use-modules (srfi srfi-1))
(define D '(((3 4))))
(let ((r 1))
       (set! D (append D '(())))
       (display D)(newline)
       (set-car! (drop D r) (car (drop D (- r 1)))))
(let ((r 2))
       (set! D (append D '(())))
       (display D)(newline)
       (set-car! (drop D r) (car (drop D (- r 1)))))
output:
(((3 4)) ())
(((3 4)) ((3 4)) ())

(use-modules (srfi srfi-1))
(define D '(((3 4))))
(map (lambda (r)
       (set! D (append D '(())))
       (display D)(newline)
       (set-car! (drop D r) (car (drop D (- r 1)))))
     '(1 2))
output:
(((3 4)) ())
(((3 4)) ((3 4)) ((3 4)))

guile (GNU Guile) 2.0.11
i686-pc-linux-gnu




Information forwarded to bug-guile <at> gnu.org:
bug#17825; Package guile. (Sat, 21 Jun 2014 21:21:02 GMT) Full text and rfc822 format available.

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

From: Mark H Weaver <mhw <at> netris.org>
To: Alírio Eyng <alirioeyng <at> gmail.com>
Cc: 17825 <at> debbugs.gnu.org, request <at> debbugs.gnu.org
Subject: Re: bug#17825: broken set! in iteration
Date: Sat, 21 Jun 2014 17:19:52 -0400
tags 17825 notabug
close 17825
thanks

Alírio Eyng <alirioeyng <at> gmail.com> writes:

> I can't see why the second code doesn't work like the first:
>
> (use-modules (srfi srfi-1))
> (define D '(((3 4))))
> (let ((r 1))
>        (set! D (append D '(())))
>        (display D)(newline)
>        (set-car! (drop D r) (car (drop D (- r 1)))))
> (let ((r 2))
>        (set! D (append D '(())))
>        (display D)(newline)
>        (set-car! (drop D r) (car (drop D (- r 1)))))
> output:
> (((3 4)) ())
> (((3 4)) ((3 4)) ())
>
> (use-modules (srfi srfi-1))
> (define D '(((3 4))))
> (map (lambda (r)
>        (set! D (append D '(())))
>        (display D)(newline)
>        (set-car! (drop D r) (car (drop D (- r 1)))))
>      '(1 2))
> output:
> (((3 4)) ())
> (((3 4)) ((3 4)) ((3 4)))

This code mutates literal lists, which is not allowed.  Specifically,
this code calls 'set-car!' on pairs that come from a literal list,
namely '(()).  The optimizer assumes that this will never happen, and
generates code based on that assumption.

So, you need to change '(()) to (list '()).  Also, if you will ever
mutate the pairs in '(((3 4))), you'll need to change that as well.

Another problem is that 'map' does not specify the order in which the
procedure is applied to the elements of the input list.  We have
'map-in-order', but both of those also build a list of the results,
which is not needed here.

Here, you should be using 'for-each', which guarantees the order of
iteration and does not build a list of the results.

The following code works as expected:

--8<---------------cut here---------------start------------->8---
(use-modules (srfi srfi-1))
(define D '(((3 4))))
(for-each (lambda (r)
            (set! D (append D (list '())))
            (display D)(newline)
            (set-car! (drop D r) (car (drop D (- r 1)))))
          '(1 2))
--8<---------------cut here---------------end--------------->8---

and outputs:

--8<---------------cut here---------------start------------->8---
(((3 4)) ())
(((3 4)) ((3 4)) ())
--8<---------------cut here---------------end--------------->8---

I'm closing this bug, but if you think there's still a bug here, feel
free to reopen it.

    Thanks!
      Mark




Added tag(s) notabug. Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Sat, 21 Jun 2014 21:21:03 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 17825 <at> debbugs.gnu.org and Alírio Eyng <alirioeyng <at> gmail.com> Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Sat, 21 Jun 2014 21:21:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#17825; Package guile. (Sat, 21 Jun 2014 21:30:02 GMT) Full text and rfc822 format available.

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

From: Mark H Weaver <mhw <at> netris.org>
To: Alírio Eyng <alirioeyng <at> gmail.com>
Cc: 17825 <at> debbugs.gnu.org
Subject: Re: bug#17825: broken set! in iteration
Date: Sat, 21 Jun 2014 17:29:05 -0400
Mark H Weaver <mhw <at> netris.org> writes:

> tags 17825 notabug
> close 17825
> thanks
>
> Alírio Eyng <alirioeyng <at> gmail.com> writes:
>
>> I can't see why the second code doesn't work like the first:
>>
>> (use-modules (srfi srfi-1))
>> (define D '(((3 4))))
>> (let ((r 1))
>>        (set! D (append D '(())))
>>        (display D)(newline)
>>        (set-car! (drop D r) (car (drop D (- r 1)))))
>> (let ((r 2))
>>        (set! D (append D '(())))
>>        (display D)(newline)
>>        (set-car! (drop D r) (car (drop D (- r 1)))))
>> output:
>> (((3 4)) ())
>> (((3 4)) ((3 4)) ())
>>
>> (use-modules (srfi srfi-1))
>> (define D '(((3 4))))
>> (map (lambda (r)
>>        (set! D (append D '(())))
>>        (display D)(newline)
>>        (set-car! (drop D r) (car (drop D (- r 1)))))
>>      '(1 2))
>> output:
>> (((3 4)) ())
>> (((3 4)) ((3 4)) ((3 4)))
>
> This code mutates literal lists, which is not allowed.  Specifically,
> this code calls 'set-car!' on pairs that come from a literal list,
> namely '(()).  The optimizer assumes that this will never happen, and
> generates code based on that assumption.

Actually, this isn't even a question of optimization.  It is simply the
fact that '(()) returns the same pair every time, and the 'set-car!'
mutates it to '((3 4)).  In some future version of Guile, we hope to
detect this error somehow, perhaps by keeping literals in read-only
memory.

(list '()), on the other hand, returns a freshly-allocated pair each
time it is called.

      Mark




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 20 Jul 2014 11:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 10 years and 339 days ago.

Previous Next


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