在 Scheme 中检索列表的第 n 个 cdr
Retrieve nth cdr of a list in Scheme
我想要 return 列表的第 n 个 cdr。例如,我说
(nth-cdr 3 '(a b c d e))
并且我会得到 (c d e)
作为输出。我不确定我的代码哪里出了问题。
我的做法是这样的。我会检查 (= num 0)
如果是,我会 return 列表。如果没有,我将递归调用 nth-cdr
并从 num
和 cdr list
中减去 1
代码是这样
(define arbitrary-cdr (lambda (num list)
(if (= num 0)
'()
(arbitrary-cdr (- num 1) (cdr list))
)))
但是,当我尝试 (arbitrary-cdr 3 ‘(a b c d e))
时出现此错误
‘: undefined;
cannot reference an identifier before its definition
我不确定这是什么意思。当我这么说时,这意味着我达到了基本情况并且只想 return 列表。不过我觉得我的逻辑是正确的。
您发布的第一个代码是:
(define arbitrary-cdr
(lambda (num list)
(if (= num 0)
(list)
(arbitrary-cdr (- num 1) (cdr list)))))
您收到的错误是:
scratch.rkt> (arbitrary-cdr 3 '(a b d c e))
; application: not a procedure;
; expected a procedure that can be applied to arguments
; given: '(c e)
问题是您使用 list
作为 arbitrary-cdr
过程的参数;由于Racket是lisp-1,程序没有自己的命名空间,所以这里重新定义list
。使用 (list)
和 list
重新定义代码试图调用 ((c e))
,但 (c e)
不是过程。
这是一个很好的例子,说明了为什么您应该 不 使用 list
或其他内置过程标识符作为 Scheme 或 Racket 中您自己的过程定义的参数。你可以在 Common Lisp 中避开这个问题,因为 Common Lisp 是一个 lisp-2,即,有一个单独的函数命名空间。
使用更新后的代码:
(define arbitrary-cdr
(lambda (num list)
(if (= num 0)
'()
(arbitrary-cdr (- num 1) (cdr list)))))
我没有收到您报告的错误;也许您的代码与您发布的不完全相同。但是,您的代码逻辑存在错误。事实上,一个空列表将总是 returned:
scratch.rkt> (arbitrary-cdr 3 '(a b c d e f))
'()
问题是当达到基本情况时,您应该 return 输入列表,而不是空列表。也就是说,给定 (arbitrary-cdr 0 '(a b c))
,您希望结果为 (a b c)
。这也意味着你的测试用例是错误的; (arbitrary-cdr 0 '(a b c d e))
--> '(a b c d e)
和 (arbitrary-cdr 3 '(a b c d e))
--> '(d e)
.
这是您重写的代码,使用 xs
而不是 list
来避免重新定义,并且 returning xs
而不是基本情况下的空列表已达到:
(define arbitrary-cdr
(lambda (num xs)
(if (= num 0)
xs
(arbitrary-cdr (- num 1) (cdr xs)))))
交互示例:
scratch.rkt> (arbitrary-cdr 0 '(a b c d e))
'(a b c d e)
scratch.rkt> (arbitrary-cdr 1 '(a b c d e))
'(b c d e)
scratch.rkt> (arbitrary-cdr 3 '(a b c d e))
'(d e)
我想要 return 列表的第 n 个 cdr。例如,我说
(nth-cdr 3 '(a b c d e))
并且我会得到 (c d e)
作为输出。我不确定我的代码哪里出了问题。
我的做法是这样的。我会检查 (= num 0)
如果是,我会 return 列表。如果没有,我将递归调用 nth-cdr
并从 num
和 cdr list
代码是这样
(define arbitrary-cdr (lambda (num list)
(if (= num 0)
'()
(arbitrary-cdr (- num 1) (cdr list))
)))
但是,当我尝试 (arbitrary-cdr 3 ‘(a b c d e))
‘: undefined;
cannot reference an identifier before its definition
我不确定这是什么意思。当我这么说时,这意味着我达到了基本情况并且只想 return 列表。不过我觉得我的逻辑是正确的。
您发布的第一个代码是:
(define arbitrary-cdr
(lambda (num list)
(if (= num 0)
(list)
(arbitrary-cdr (- num 1) (cdr list)))))
您收到的错误是:
scratch.rkt> (arbitrary-cdr 3 '(a b d c e))
; application: not a procedure;
; expected a procedure that can be applied to arguments
; given: '(c e)
问题是您使用 list
作为 arbitrary-cdr
过程的参数;由于Racket是lisp-1,程序没有自己的命名空间,所以这里重新定义list
。使用 (list)
和 list
重新定义代码试图调用 ((c e))
,但 (c e)
不是过程。
这是一个很好的例子,说明了为什么您应该 不 使用 list
或其他内置过程标识符作为 Scheme 或 Racket 中您自己的过程定义的参数。你可以在 Common Lisp 中避开这个问题,因为 Common Lisp 是一个 lisp-2,即,有一个单独的函数命名空间。
使用更新后的代码:
(define arbitrary-cdr
(lambda (num list)
(if (= num 0)
'()
(arbitrary-cdr (- num 1) (cdr list)))))
我没有收到您报告的错误;也许您的代码与您发布的不完全相同。但是,您的代码逻辑存在错误。事实上,一个空列表将总是 returned:
scratch.rkt> (arbitrary-cdr 3 '(a b c d e f))
'()
问题是当达到基本情况时,您应该 return 输入列表,而不是空列表。也就是说,给定 (arbitrary-cdr 0 '(a b c))
,您希望结果为 (a b c)
。这也意味着你的测试用例是错误的; (arbitrary-cdr 0 '(a b c d e))
--> '(a b c d e)
和 (arbitrary-cdr 3 '(a b c d e))
--> '(d e)
.
这是您重写的代码,使用 xs
而不是 list
来避免重新定义,并且 returning xs
而不是基本情况下的空列表已达到:
(define arbitrary-cdr
(lambda (num xs)
(if (= num 0)
xs
(arbitrary-cdr (- num 1) (cdr xs)))))
交互示例:
scratch.rkt> (arbitrary-cdr 0 '(a b c d e))
'(a b c d e)
scratch.rkt> (arbitrary-cdr 1 '(a b c d e))
'(b c d e)
scratch.rkt> (arbitrary-cdr 3 '(a b c d e))
'(d e)