为什么这段代码正常工作?

时间:2016-10-06 13:12:30

标签: 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次第5次),最后它将在第7行再次反转(第三次)。

由于列表反转3次,因此应该输出反转列表(不带零),但是输出中会显示非反转列表。解释中的缺陷在哪里?

1 个答案:

答案 0 :(得分:2)

你必须记住,当循环返回时,程序继续在第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)