为什么这个递归函数将空集合传递给“take”?
Why does this recursive function pass an empty collection to `take`?
我正在尝试在 Scheme 中编写 Clojure 的 partition-all
函数的实现:
(define (take lst n)
(if (= n 0)
'()
(cons (car lst) (take (cdr lst) (- n 1)))))
(define (partition-all n step coll)
(if (not (null? coll))
(cons (take coll (min n (length coll)))
(partition-all n step (list-tail coll step)))))
但是口译员对我大吼:
cdr: expected pair in argument #1
这意味着,在某些时候,一个空列表 '()
被传递给 take
,由于 partition-all
中的条件 (not (null? coll))
,这永远不会发生功能。
我的功能有什么问题?
根据我在评论中所说的内容,我非常确定 而不是 take
中的 cdr
给您带来了问题。 运行 你在 ideone 上的诡计代码给了我:
ERROR: In procedure list-tail:
ERROR: In procedure list-tail: Wrong type argument in position 1 (expecting pair): ()
因此,问题是您正在尝试获取不够长的列表尾部。这可以通过仅取 step
和集合长度中的最小值来缓解:
(define (take lst n)
(if (= n 0)
'()
(cons (car lst) (take (cdr lst) (- n 1)))))
(define (partition-all n step coll)
(if (not (null? coll))
(cons (take coll (min n (length coll)))
(partition-all n step (list-tail coll (min (length coll) step))))
;;^^^^^^^^^^^^^^^^^
'()
;;^^^
))
(display (partition-all 3 2 '(a b c d e f g)))
; => ((a b c) (c d e) (e f g) (g))
请注意,我还在 if
中添加了一个 else 案例,否则结果列表不是以 '()
(空列表)结束,而是以一个未指定的值结束。
另请注意,您的两个函数都不是尾递归的。
我正在尝试在 Scheme 中编写 Clojure 的 partition-all
函数的实现:
(define (take lst n)
(if (= n 0)
'()
(cons (car lst) (take (cdr lst) (- n 1)))))
(define (partition-all n step coll)
(if (not (null? coll))
(cons (take coll (min n (length coll)))
(partition-all n step (list-tail coll step)))))
但是口译员对我大吼:
cdr: expected pair in argument #1
这意味着,在某些时候,一个空列表 '()
被传递给 take
,由于 partition-all
中的条件 (not (null? coll))
,这永远不会发生功能。
我的功能有什么问题?
根据我在评论中所说的内容,我非常确定 而不是 take
中的 cdr
给您带来了问题。 运行 你在 ideone 上的诡计代码给了我:
ERROR: In procedure list-tail:
ERROR: In procedure list-tail: Wrong type argument in position 1 (expecting pair): ()
因此,问题是您正在尝试获取不够长的列表尾部。这可以通过仅取 step
和集合长度中的最小值来缓解:
(define (take lst n)
(if (= n 0)
'()
(cons (car lst) (take (cdr lst) (- n 1)))))
(define (partition-all n step coll)
(if (not (null? coll))
(cons (take coll (min n (length coll)))
(partition-all n step (list-tail coll (min (length coll) step))))
;;^^^^^^^^^^^^^^^^^
'()
;;^^^
))
(display (partition-all 3 2 '(a b c d e f g)))
; => ((a b c) (c d e) (e f g) (g))
请注意,我还在 if
中添加了一个 else 案例,否则结果列表不是以 '()
(空列表)结束,而是以一个未指定的值结束。
另请注意,您的两个函数都不是尾递归的。