在没有MAPCAR的列表列表中搜索元素

Sub*_*wal 0 recursion common-lisp

我尝试了一个问题,即创建一个程序来替换A列表中元素的所有实例,而不是L使用T元素NIL.赌注是不使用mapcar.

这是我之前做的.我正在存储所有TNIL在新列表中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))))
Run Code Online (Sandbox Code Playgroud)

当前行为:该程序运行良好,除了在搜索NIL自己时,但这种特殊情况在这里并不重要.

我的代码运行的示例很少: -

   (SRC 'g '(a g g o t g))
> (nil t t nil nil t)
Run Code Online (Sandbox Code Playgroud)

NIL在列表中搜索时: -

   (SRC nil '(t a t nil nil))
> (nil nil nil t)
Run Code Online (Sandbox Code Playgroud)

在这个单一的情况下,我们的程序结束于在列表中找到第一个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))))
Run Code Online (Sandbox Code Playgroud)

现在,我期望从此代码输出如下:

  (SRC 'e '(a b e c (e g e) h t e))
> (nil nil t nil (t nil t) nil nil t)
Run Code Online (Sandbox Code Playgroud)

相反,我的代码永远运行,导致堆栈溢出,我无法弄清楚任何带有callstacks或回溯的东西.

Rai*_*wig 7

由于缺少缩进而导致代码难以理解.

您的代码是不可读的,因为您的代码没有缩进.

(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))))
Run Code Online (Sandbox Code Playgroud)

让我们缩进你的代码.

(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))))
Run Code Online (Sandbox Code Playgroud)

风格和基本错误

基本错误或编程风格问题:

  • defun不应该嵌套.defun不是用于定义本地功能.defun应该只用于全局功能.使用fletlabels用于本地功能.
  • 使用firstrest不是carcdr
  • 使用说话变量
  • 使用小写

不要从嵌套函数开始

我会从没有嵌套函数开始.

(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))))
Run Code Online (Sandbox Code Playgroud)

简化递归

但是,您可以使用通常的递归模式大大简化它:

(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
Run Code Online (Sandbox Code Playgroud)

注意

一般不喜欢编程递归函数,因为Lisp的其实已经提供MAPMAPCAR-那些提供映射功能在一个地方,它不需要烘烤递归映射到自己的各项功能.

最好使用更高级别的迭代工具,如LOOP:

CL-USER 13 > (loop for e in '(a b a b)
                   collect (equal 'a e))
(T NIL T NIL)
Run Code Online (Sandbox Code Playgroud)

嵌套列表

您可以通过添加第一个元素作为列表的案例测试然后在这种情况下执行某些操作来使上述函数适应嵌套列表...

(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)))))
Run Code Online (Sandbox Code Playgroud)

调试

使用trace和/或step查看代码正在执行的操作.

  • @Subham:我认为您需要先改进代码才能使其可读.调试不可读和未格式化的代码通常是浪费时间.然后我会追踪这些功能,看看他们在做什么.请参阅宏CL:TRACE. (2认同)