Hi,

I was reading a thread on an imageboard[0] the other day, then I came
across a most peculiar "bug", if it even is one. Since the original
example was a bit dense (it tried to solve a problem someone else had
posted, that's not relevant here), I tried to construct a minimal
working example to discuss here.

Compare

    (define (reverse-iota-1 max)
      (let ((numbers '(start)))
        (let loop ((val 0))
          (append! numbers
                   (if (< max val)
                       '()
                       (begin
                         (loop (1+ val))
                         (list val)))))
        numbers))

and

    (define (reverse-iota-2 max)
      (let ((numbers '(start)))
        (let loop ((val 0))
          (append! numbers
                   (if (< max val)
                       '()
                       (begin
                         (loop (1+ val))
                         (list val)))))
        (cdr numbers)))

(I know, the style is horrible, but that's not the point. Also, both
have an internal state, so you have to re-eval the function every time
before starting the function itself.)

The only difference is in the last line. The first function returns the
entire list (with the start symbol), and the second tries to chop it
off.

But what happens is that (reverse-iota-1 4) evals to '(start 3 2 1 0)
while (reverse-iota-2 4) just returns '()!

This seems weird, since my intuition, and that of the poster above, was
that all that should change in reverse-iota-2 is that the "start" symbol
should fall away.

It's obvious that this has something to do with the destructive
"append!", but I'm not quite sure what leads to this unexpected result.
Is it maybe a optimisation error? Any opinions?

[0]: https://lainchan.org/%CE%BB/res/12185.html#15066 (SFW)

-- 
        With kind regards,
        Philip K.

Attachment: signature.asc
Description: PGP signature

Reply via email to