Esquema / Esquema Achatado Explicações

Alguém pode me ajudar a quebrar exatamente a ordem de execução das seguintes versões do flatten? Estou usando o Racket.

versão 1, é da própria raquete, enquanto a versão dois é mais comum? implementação.

(define (flatten1 list)
  (let loop ([l list] [acc null])
    (printf "l = ~a acc = ~a\n" l acc)
    (cond [(null? l) acc]
          [(pair? l) (loop (car l) (loop (cdr l) acc))]
          [else (cons l acc)])))

(define (flatten2 l)
  (printf "l = ~a\n" l)
  (cond [(null? l) null]
        [(atom? l) (list l)]
        [else (append (flatten2 (car l)) (flatten2 (cdr l)))]))

Agora, executando o primeiro exemplo com '(1 2 3) produz:

l = (1 2 3) acc = ()
l = (2 3) acc = ()
l = (3) acc = ()
l = () acc = ()
l = 3 acc = ()
l = 2 acc = (3)
l = 1 acc = (2 3)
'(1 2 3)

enquanto o segundo produz:

l = (1 2 3)
l = 1
l = (2 3)
l = 2
l = (3)
l = 3
l = ()
'(1 2 3)

A ordem de execução parece diferente. No primeiro exemplo, parece que o segundo loop(loop (cdr l) acc) está disparando antes do primeiro loop porque '(2 3) está imprimindo imediatamente. Enquanto no segundo exemplo, 1 imprime antes do '(2 3), que parece que a primeira chamada a achatar dentro do append é avaliada primeiro.

Eu estou passando pelo Little Schemer, mas estes são exemplos mais difíceis que eu realmente poderia usar alguma ajuda.

Muito obrigado.

questionAnswers(2)

yourAnswerToTheQuestion