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被嵌套了,我想这可能是一个通常的做法,尽管我的教科书没有提到这一点。我会在问题中纠正它,但我希望在收到答案后,我不会因为编辑而被责骂(