Jon*_*h P 0 lisp recursion position common-lisp
我试图在列表中找到原子的位置.
预期成绩:
(position-in-list 'a '(a b c d e)) 给出0
(position-in-list 'b '(a b c d e)) 给出1
(position-in-list 'Z '(a b c d e)) 没有.
我有一个函数,当项目在列表中时,正确地给出位置:
(defun position-in-list (letter list)
(cond
((atom list) nil)
((eq (car list) letter) 0)
(t (+ 1 (position-in-list letter (cdr list))))))
Run Code Online (Sandbox Code Playgroud)
问题是,当项目不存在时它不返回nil,就好像它达到(atom list)nil它会给出这个错误:*** - 1+: nil is not a number当它取消堆栈时,它会尝试将值添加到nil.
有没有办法调整这个功能(保持相同的结构),以便nil当项目不在列表中时正确返回?
笔记:
我知道库中有一个position函数,但我不想使用它.
我知道我的问题与此类似,但我上面提到的问题没有得到解决.
*编辑* 感谢大家的答案.虽然我没有必要的知识来理解你提到的所有建议,但它很有帮助.
我找到了另一个解决我问题的方法:
(defun position-in-list (letter liste)
(cond
((atom liste) nil)
((equal letter (car liste)) 0)
((position-in-list letter (cdr liste)) (+ 1 (position-in-list letter (cdr liste)))) ) )
Run Code Online (Sandbox Code Playgroud)
一种可能的解决方案是使递归函数成为另一个函数的局部函数.最后,一个人将从周围的函数返回 - 因此您不需要NIL从每个递归调用返回结果.
本地递归函数从函数返回
可以使用定义本地递归函数LABELS.
(defun position-in-list (letter list)
(labels ((position-in-list-aux (letter list)
(cond
((atom list) (return-from position-in-list nil))
((eql (first list) letter) 0)
(t (+ 1 (position-in-list-aux
letter (cdr list)))))))
(position-in-list-aux letter list)))
Run Code Online (Sandbox Code Playgroud)
这RETURN-FROM是可能的,因为从本地函数可以看到返回的函数.
递归函数返回另一个函数
也可以使用CATCH和将控制返回到另一个函数THROW:
(defun position-in-list (letter list)
(catch 'position-in-list-catch-tag
(position-in-list-aux letter list)))
(defun position-in-list-aux (letter list)
(cond
((atom list) (throw 'position-in-list-catch-tag nil))
((eql (first list) letter) 0)
(t (+ 1 (position-in-list-aux
letter (cdr list))))))
Run Code Online (Sandbox Code Playgroud)
测试功能EQL
另请注意,按惯例的默认测试功能EQL不是EQ.这也允许使用数字和字符.