Recursion 如果在列表中找不到号码,如何返回false
因此,我试图解决这个硬件问题:编写一个函数,它包含两个参数,一个列表和一个数字,该函数返回列表中最左边的数字的索引。例如:Recursion 如果在列表中找不到号码,如何返回false,recursion,functional-programming,scheme,lisp,racket,Recursion,Functional Programming,Scheme,Lisp,Racket,因此,我试图解决这个硬件问题:编写一个函数,它包含两个参数,一个列表和一个数字,该函数返回列表中最左边的数字的索引。例如: 如果”(1234)和num=3,则返回2 如果'(3 2 3 4)和num=3,则返回0 我能做到这一点,但如果找不到号码怎么办?如果在列表中找不到num时要返回false,该怎么办?我该怎么做 请记住,我试图用正确的递归,而不是尾部递归 这是我的密码 (define (first_elt_occ lst num) (cond ((null? l
- 如果
和”(1234)
,则返回num=3
2
- 如果
和'(3 2 3 4)
,则返回num=3
0
num
时要返回false,该怎么办?我该怎么做
请记住,我试图用正确的递归,而不是尾部递归
这是我的密码
(define (first_elt_occ lst num)
(cond
((null? lst) #f)
((eq? (car lst) num) 0)
(else
(+ 1 (first_elt_occ (cdr lst) num)))))
(first_elt_occ '(1 2 3 3 4) 3) ;2
(first_elt_occ '(3 2 3 3 4) 3) ;0
(first_elt_occ '(1 2 5 4 3) 3) ;4
(first_elt_occ '(1 2 5 4 3) 6) ;Error
;(makes sense because you can't add boolean expression)
我的另一个问题是,如果我被要求返回列表中最右边出现的数字的索引(正确的递归),我将如何处理这个问题。例如:”(3 4 5 4 3 7)
,num=3
返回4
谢谢大家! 正如评论中所建议的,如果我们使用尾部递归来实现过程,这将更容易——顺便问一下,尾部递归是“正确的递归”,你怎么会不这么认为 通过定义一个名为
loop
的帮助程序,并将累积结果传递给一个参数,我们可以返回#f
或元素的索引:
(define (first_elt_occ lst num)
(let loop ((lst lst) (acc 0))
(cond
((null? lst) #f)
((equal? (car lst) num) acc)
(else (loop (cdr lst) (add1 acc))))))
如果,对于某些奇怪的需求,您不能在解决方案中使用尾部递归,则可以重写原始解决方案,以说明答案为#f
时的情况-但这并没有那么优雅或高效:
(define (first_elt_occ lst num)
(cond
((null? lst) #f)
((equal? (car lst) num) 0)
(else
(let ((result (first_elt_occ (cdr lst) num)))
(if (not result) #f (add1 result))))))
无论哪种方式,它都能按预期工作:
(first_elt_occ '(1 2 3 3 4) 3) ; 2
(first_elt_occ '(3 2 3 3 4) 3) ; 0
(first_elt_occ '(1 2 5 4 3) 3) ; 4
(first_elt_occ '(1 2 5 4 3) 6) ; #f
> (first_elt_occ '(1 2 3 3 4) 3)
2
> (first_elt_occ '(3 2 3 3 4) 3)
0
> (first_elt_occ '(3 2 3 3 4) 5)
#f
不清楚您为什么反对尾部递归。你说的是“适当的递归”,这不是任何人使用的技术术语,但我假设你指的是非尾部递归:用SICP术语来说,是递归过程,而不是迭代过程。请放心,尾部递归是非常合适的,并且通常比非尾部递归更好,前提是不必进行其他权衡来启用尾部递归
正如奥斯卡·洛佩斯所说,用尾部递归确实更容易解决这个问题。但如果你坚持,当然可以用艰难的方式解决它。您必须避免盲目地将1添加到结果中:相反,检查它,如果它是一个数字,则将1添加到结果中,如果它为false,则返回不变的结果。例如,请参阅
number?
谓词。我不建议实际采用这种方法,因为正常的尾部递归实现效率更高、更简单、更容易理解,但在故障情况下,您可以使用continuation来短路解除调用堆栈:
(define (first_elt_occ lst num)
(call/cc
(lambda (return)
(letrec ((loop (lambda (lst)
(cond
((null? lst) (return #f))
((= (car lst) num) 0)
(else (+ 1 (loop (cdr lst))))))))
(loop lst)))))
第一次出现的基本查找是
但这不会返回索引。如何添加它
(define (first_elt_occ lst num)
(and (not (null? lst))
(or (and (equal (car lst) num) 0)
(+ 1 (first_elt_occ (cdr lst) num)))))
它有用吗?如果元素不在那里就不会!那会导致一个错误。如何解决这个问题?更改+
,就是这样
(define (first_elt_occ lst num)
(let ((+ (lambda (a b) (if b (+ a b) b))))
(and (not (null? lst))
(or (and (= (car lst) num) 0)
(+ 1 (first_elt_occ (cdr lst) num))))))
现在,它如预期的那样工作:
(first_elt_occ '(1 2 3 3 4) 3) ; 2
(first_elt_occ '(3 2 3 3 4) 3) ; 0
(first_elt_occ '(1 2 5 4 3) 3) ; 4
(first_elt_occ '(1 2 5 4 3) 6) ; #f
> (first_elt_occ '(1 2 3 3 4) 3)
2
> (first_elt_occ '(3 2 3 3 4) 3)
0
> (first_elt_occ '(3 2 3 3 4) 5)
#f
为了得到你想要的第二个函数,我们将它重新构造一点,变成
(define (first_elt_occ lst num)
(let ((+ (lambda (a b) ...... )))
(and (not (null? lst))
(+ (and (= (car lst) num) 0)
(first_elt_occ (cdr lst) num)))))
现在,新的
+
应该是什么?你能把这个做完吗?这很简单 尾部递归非常简单(而且效率更高)……要求很高!:)您在同一帖子中有两个不同的问题,让我们在这里解决第一个问题,并在您找到第一个问题的满意答案后发布第二个问题。谢谢。我的教授希望我们使用尾部递归和“适当递归”来实现这个问题——堆栈的增长和收缩。我已经知道如何在尾部递归中实现它。谢谢。我的教授希望我们使用尾部递归和“适当递归”来实现这个问题——堆栈的增长和收缩。我已经知道如何在尾部递归中实现它。