guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

Using 2.0.11 (gotta upgrade!):

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]