Pierre Lairez <pierre.lai...@gmail.com> 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