guile-devel
[Top][All Lists]

Re: Do-loop enigma with two variables

 From: Taylan Ulrich Bayırlı/Kammer Subject: Re: Do-loop enigma with two variables Date: Sat, 16 Jul 2016 10:55:28 +0200 User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

```Pierre Lairez <address@hidden> writes:

> Dear guile users,
>
> When running the following loop:
> (do ((i 1 (+ 1 i))
>      (j 0 i))
>     ((> i 4) (newline))
>   (display (list i j)))
>
> I expect without hesitation to read
> (1 0)(2 1)(3 2)(4 3)
>
> To my surprise, I obtain
> (1 0)(2 2)(3 3)(4 4)
>
> After macro-expansion, the loop above is rewritten in the following:
> (letrec ((loop
>           (λ (i j)
>             (if (> i 4)
>                 (newline)
>                 (begin
>                   (display (list i j))
>                   (loop (+ 1 i) i))))))
>   (loop 1 0))
>
> The equality j = i + 1 is clearly a loop invariant, the function “loop“
> is *never* called with two equal arguments. So I cannot understand why
> (2 2) may possibly appear in the output. What do I not see?
>
> Best regards,
>
> Pierre

I suspect this is a bug in the optimizer; guile-devel CC'd.

scheme@(guile-user)> ,expand (do ((i 1 (+ 1 i))
(j 0 i))
((> i 4) (newline))
(display (list i j)))
\$5 = (let loop ((i 1) (j 0))
(if (> i 4)
(begin (if #f #f) (newline))
(begin (display (list i j)) (loop (+ 1 i) i))))

;; Looks good to me.  Let's use the interpreter on it:

scheme@(guile-user)> (eval '(let loop ((i 1) (j 0))
(if (> i 4)
(begin (if #f #f) (newline))
(begin (display (list i j)) (loop (+ 1 i)
i))))
((@ (rnrs eval) environment) '(guile)))
(1 0)(2 1)(3 2)(4 3)

;; Looks good to me as well.  Now the compiler's optimizer:

scheme@(guile-user)> ,optimize (let loop ((i 1) (j 0))
(if (> i 4)
(begin (if #f #f) (newline))
(begin (display (list i j)) (loop (+ 1 i)
i))))
\$6 = (begin
(display (list 1 0))
(begin
(display (list 2 2))
(begin
(display (list 3 3))
(begin (display (list 4 4)) (newline)))))

;; Beep!

(Note that the Guile REPL compiles the given expressions by default.)

Taylan

```