这是我的问题:
不使用MEMBER,完成递归函数POS的以下定义
如果L是列表而E是L的元素,则(POS E L)返回第一个的位置
在L中出现E,并且如果E不是L的元素则(POS E L)返回0.
这是解决方案:
(DEFUN POS (E L)
(COND ((ENDP L) 0)
((EQUAL E (CAR L)) 1 )
(T
(+ 1 (POS E (CDR L)) )
)))
如果我要查找的元素在列表中,该算法可以正常工作。我的问题是,当元素不在列表中时,我将得到列表的长度。
示例:
list[1,2,3,4] Find: 5 will reurn 4
如果找不到元素,如何让它返回0。因为它是函数式编程,所以我不能使用循环或变量。
答案 0 :(得分:4)
您总是返回(+ 1 <recursive-call>)
。但是,如果递归结果为零呢?您应该在计算结果之前检查该返回值。
顺便说一下,Common Lisp的方式是:
(or (position E L :test #'equal) 0)
答案 1 :(得分:0)
正如@coredump所解释的那样,问题是你总是在结果中加1,即使你还没找到元素。我会通过在函数POS
中添加一个额外的参数来跟踪列表中的当前位置:
(defun pos (element list &optional (start 0))
(cond ((endp list) 0)
((equal element (first list)) (1+ start))
(t (pos element (rest list) (1+ start)))))
测试:
(pos 'a '(b a c d a))
2
(pos 'a '(a d a f g))
1
(pos 'w '(a b c d e f))
0
一个额外的好处:由于递归调用处于尾部调用位置,此函数会生成迭代进程(但是,ANSI Common Lisp不保证它会进行尾调用优化!AFAIK,CLisp不会& #39; t do do; SBCL和CCL将用于优化代码,请参阅DECLARE
)。更惯用的Common Lisp解决方案将使用LOOP
:
(defun pos (element list)
(loop for x in list
counting x into pos
when (equal element x)
return pos
end
finally (return 0)))