这是我之前作业的一个问题。我们目前正在使用DrRacket在Racket中进行编程,并且在学期初期就完成了对自然递归的审查。
具体问题是通过完成嵌套list-ref
来完成nth-cdr
的实施。这是给出的代码:
(define list-ref
(lambda (ls n)
(letrec
((nth-cdr
(lambda (n)
;;body of function
(car (nth-cdr n)))))
非常简单,说明是实现nth-cdr
的自然递归版本。这就是我最终得到的结果:
(define list-ref
(lambda (ls n)
(letrec
((nth-cdr
(lambda (n)
(cond
((zero? n) ls)
(else (list-ref (cdr ls) (sub1 n)))
))))
(car (nth-cdr n)))))
传递nth-cdr
0
以外的任何号码都会导致合同违规行为发生。在car
的正文中letrec
。
(list-ref '(1 2 3) 0) ==> '1
(list-ref '(1 2 3) 1) ==> *expected: pair?* *given: 2*
ls
范围内nth-cdr
的范围是否有问题?我不知道为什么let-rec
的主体会接受car
的{{1}}并抱怨输出?
任何人都有可能非常简单问题的答案吗?
答案 0 :(得分:2)
list-ref
很容易编写为尾递归函数:
(define (list-ref lst n)
(if (zero? n)
(car lst)
(list-ref (cdr lst) (- n 1))))
更新:你说你的解决方案必须遵循模板吗?这是一种hacky方式,但与Óscar的解决方案不同,它不使用set!
。但它仍然很难看:
(define list-ref
(lambda (ls n)
(letrec
((nth-cdr
(lambda (n)
(if (number? n)
(nth-cdr (cons ls n))
(let ((ls (car n))
(n (cdr n)))
(if (zero? n)
ls
(nth-cdr (cons (cdr ls) (- n 1)))))))))
(car (nth-cdr n)))))
答案 1 :(得分:1)
你的帮助程序必须在列表和索引上前进,它不会只是递减数字。它应该自称,而不是外部程序!此外,一些错误检查不会受到影响,请尝试:
(define list-ref
(lambda (ls n)
(letrec
((nth-cdr
(lambda (ls n)
(cond
((null? ls) #f)
((zero? n) (car ls))
(else (nth-cdr (cdr ls) (sub1 n)))
))))
(nth-cdr ls n))))
要明确的是,这里真的不需要帮助程序,为了简化我们可以做到这一点:
(define list-ref
(lambda (ls n)
(cond
((null? ls) #f)
((zero? n) (car ls))
(else (list-ref (cdr ls) (sub1 n))))))
<强>更新强>
既然你已经在评论中提到有一些额外的限制,我可以为你提供以下解决方案 - 它有效,但相信我,它很难看。我们不应该为这个简单的问题改变状态,这可以通过传递一个额外的参数来避免。无论如何,你走了:
(define list-ref
(lambda (ls n)
(letrec
((nth-cdr
(lambda (n)
(cond ((null? ls) '(#f))
((zero? n) ls)
(else
(set! ls (cdr ls))
(nth-cdr (sub1 n)))))))
(car (nth-cdr n)))))