#scheme #racket
#схема #ракетка
Вопрос:
Я думал, что следующий код не будет правильно удалять начальные и конечные нули, но это так:
(define f
(λ (l)
(let loop () ; 1 (code line no.)
(when (= 0 (first l)) ; 2
(set! l (rest l)) ; 3
(loop)) ; 4
(set! l (reverse l) ) ; 5
(when (= 0 (first l)) (loop))) ; 6
(reverse l))) ; 7
(f '(0 0 2 5 0 6 8 9 0 0 0))
Вывод:
'(2 5 0 6 8 9)
Я думал, что после удаления начальных нулей список будет перевернут в строке 5; затем из строки 6 он вернется к строке 1 и удалит конечные нули (которые теперь являются ведущими в перевернутом списке). Затем этот список снова изменится (во второй раз в строке 5) и, наконец, он снова изменится (в третий раз) в строке 7.
Поскольку список переворачивается 3 раза, выводом должен быть перевернутый список (без нулей), однако на выходе отображается не перевернутый список. Где недостаток в объяснении?
Комментарии:
1. Опубликованный вами код не тот, на который вы ссылались. Этот код сочетает в себе мутацию и рекурсию, что является неприятной комбинацией для размышлений. Тот, который вы связали, является чисто функциональным.
2. Я изменил код в этой ссылке после того, как обнаружил, что он неисправен. Я удалил ссылку из своего вопроса. Спасибо, что указали на недосмотр.
Ответ №1:
Вы должны помнить, что при возврате цикла программа продолжает выполняться после строки 4. Это происходит для каждого вызова цикла. Итак, если есть n начальных нулей и m конечных нулей reverse
, будет вызван n 1 m 1 1 = n m 3
(последний 1
обратный в конце программы), что в примере равно 8.
Однако вы правы в том, что программа не работает как запущенная
(f '(0 0 2 5 0 6 8 9 0 0))
выведет
'(9 8 6 0 5 2)
Комментарии:
1. Следовательно, моя догадка была верной, что этот код не полностью корректен.