Ракетка / Схема Свести Объяснения
Может кто-нибудь помочь мне разобрать точно порядок исполнения для следующих версий 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), который выглядит как первый вызов сглаживания внутри добавления добавляется первым.
Я собираюсь пройтись по Маленькому Планировщику, но это более сложные примеры, в которых я мог бы действительно помочь.
Большое спасибо.