Ракетка / Схема Свести Объяснения

Может кто-нибудь помочь мне разобрать точно порядок исполнения для следующих версий flatten? Я использую ракетку.

1-я версия от самой ракетки, а вторая - более распространенная? реализация.

(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)))]))

Теперь, запустив первый пример с '(1 2 3), получим:

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)

в то время как второй производит:

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

Порядок исполнения кажется другим. В первом примере это выглядит как второй цикл(loop (cdr l) acc) стреляет перед первым циклом, поскольку '(2 3) печатает сразу. Принимая во внимание, что во втором примере 1 печатает перед '(2 3), который выглядит как первый вызов, чтобы сгладить внутри append, оценивается первым.

Я прохожу «Маленький мошенник», но это более сложные примеры, на которых я мог бы действительно помочь.

Большое спасибо.

Ответы на вопрос(2)

Ваш ответ на вопрос