Recursion 在没有MAPCAR的列表列表中搜索元素
我试图制作一个程序,用Recursion 在没有MAPCAR的列表列表中搜索元素,recursion,common-lisp,Recursion,Common Lisp,我试图制作一个程序,用T替换列表L中元素a的所有实例,而不是用NIL替换元素。赌注是不要使用mapcar 这是我之前做的。我将所有T和NIL存储在一个新列表POS中,然后返回POS (defun SRC (A L) (defun _SRC (A L POS) (COND ((NOT (EQUAL (CAR L) NIL)) (_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L)))))) (
T
替换列表L
中元素a
的所有实例,而不是用NIL
替换元素。赌注是不要使用mapcar
这是我之前做的。我将所有T
和NIL
存储在一个新列表POS
中,然后返回POS
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
当前行为:
程序运行良好,除了搜索NIL
本身,但这里不考虑这种特殊情况
我的代码运行的几个示例:-
(SRC 'g '(a g g o t g))
> (nil t t nil nil t)
在列表中搜索NIL
时:-
(SRC nil '(t a t nil nil))
> (nil nil nil t)
在这种情况下,我们的程序在查找列表中的第一个NIL时结束,对于其他搜索,程序工作正常。因此,我尝试添加在列表列表中搜索的功能。
我的更新代码,用于在不带mapcar的列表中搜索:
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((LISTP (CAR L))
(APPEND POS (LIST (SRC A (CAR L)))))
((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
现在,我希望从这段代码中得到如下输出:
(SRC 'e '(a b e c (e g e) h t e))
> (nil nil t nil (t nil t) nil nil t)
相反,我的代码会永远运行,导致堆栈溢出,我无法通过调用堆栈或回溯找出任何东西。由于缺少缩进,代码无法读取。
您的代码不可读,因为您的代码没有缩进
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL)) (_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL) (APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
让我们缩进您的代码
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
风格和基本错误
基本错误或编程风格问题:
defun
不应嵌套defun
不用于定义本地函数defun
只能用于全局函数。对本地功能使用flet
或标签
- 使用
first
和rest
代替car
和cdr
- 使用口语变量
- 使用小写字母
不要以嵌套函数开头
我会从没有嵌套函数开始
(defun _src (element list pos)
(cond ((not (equal (first list) nil))
(_src a (rest list) (append pos (list (equal element (car list))))))
((equal (first list) nil)
(append pos (list (equal element nil))))
(t pos)))
(defun src (element list)
(cdr (_src element list (list nil))))
简化递归
但是,您可以使用通常的递归模式大大简化它:
(defun mark% (element list result)
(if (null list)
result ; empty list -> return result
(mark% element ; mark the rest of the list
(rest list)
(cons (equal element (first list)) ; equal for the first element?
result))))
(defun mark (element list)
"return a list with boolean values if element is found in the list"
(reverse (mark% element list nil))) : needs to reverse the result
注意
通常不要这样编写递归函数,因为Lisp实际上已经提供了MAP
和MAPCAR
——它们在一个地方提供映射功能,并且不需要将递归映射烘焙到您自己的每个函数中
最好使用更高级别的迭代工具,如LOOP:
CL-USER 13 > (loop for e in '(a b a b)
collect (equal 'a e))
(T NIL T NIL)
嵌套列表
您可以将上述函数调整为嵌套列表,方法是为列表中的第一个元素添加一个案例测试,然后在该案例中执行某些操作
(defun mark% (element list result)
(cond ((null list)
result)
((consp (first list))
(mark% element
(rest list)
(cons (mark element (first list))
result)))
(t
(mark% element
(rest list)
(cons (equal element (first list))
result)))))
调试
使用trace
和/或step
查看您的代码在做什么。虽然这很有价值,但我还需要知道我的代码哪里出错以及为什么溢出堆栈。@Subham:我认为您需要先改进代码,使其可读。调试不可读和未格式化的代码通常是浪费时间。然后我会跟踪函数,看看它们在做什么。查看宏CL:TRACE.there。。我正确地缩进了它,希望它是正确的。@SubhamBurnwal:最好去掉嵌套的DEFUN
DEFUN
仅用于全局函数。试图将其用于本地功能是错误的,不会产生预期的效果。。如果您首先拥有全局函数,那么跟踪它们也更容易——尽管有些实现可以跟踪本地函数。在我所有的lisp程序中,我从未嵌套过它。你在这里看到的异常行为是因为我在网上的某个地方读到一个程序,其中DEFUN被嵌套了,我想这可能是一个通常的做法,尽管我的教科书没有提到这一点。我会在问题中纠正它,但我希望在收到答案后,我不会因为编辑而被责骂(