Lisp标签功能在使用前被删除

Ant*_*ias 0 lisp function common-lisp

我正在尝试使用标签的本地函数来允许我的函数递归.这是代码:

(defun  my-replace (e1 e2 L)
  "Perform a deep replace e1 with e2 in L."
  (labels ((my-replace-rec (e1 e2 L)
             "Used for recursion"
             (cond ((endp L) nil)
                   ((equal (car L) e1) (cons e2 (cdr L)))
                   ((listp (car L)) (my-replace-rec e1 e2 (car L)))
                   (t (my-replace-rec e1 e2 (cdr L)))))))
    (my-replace-rec e1 e2 L))
Run Code Online (Sandbox Code Playgroud)

当我有slime评估函数并尝试运行它:

;   Note: Deleting unused function                                                
;   (LABELS MY-REPLACE-REC)                                                     
; ;                                                                             

; Warning: This function is undefined:                                          
;   MY-REPLACE-REC
Run Code Online (Sandbox Code Playgroud)

我试图尽可能多地填写错误消息,但我正在使用Emacs(我还是很新),并尝试粘贴一个小缓冲区.

为什么会这样?它被定义和使用,但它似乎在使用之前被删除(据说因为它没有被使用).

Syl*_*ter 9

你的身份已经消失了.这是您正确设计的代码:

(defun  my-replace (e1 e2 L)
  "Perform a deep replace e1 with e2 in L."
  (labels ((my-replace-rec (e1 e2 L)
              "Used for recursion"
              (cond ((endp L) nil)
                    ((equal (car L) e1) (cons e2 (cdr L)))
                    ((listp (car L)) (my-replace-rec e1 e2 (car L)))
                    (t (my-replace-rec e1 e2 (cdr L))))))
          ;; empty labels body here.. 
          )
  ;; my-replace-rec is a global function expected to be defun-ed later
  (my-replace-rec e1 e2 L))
Run Code Online (Sandbox Code Playgroud)

labels工作就像let.您需要labels在函数体内使用创建的对象,而不是在函数被销毁之后使用.

随着:

(let ((a 10))
  ; a exists here
  )
; a doesn't exist anymore
Run Code Online (Sandbox Code Playgroud)

labels

(labels ((name (arg) arg))
  ; the function exists here
  )
;the function doesn't esist anymore
Run Code Online (Sandbox Code Playgroud)

在你的代码中,你my-replace-rec在标签的主体中制作你什么也不做,在my-replace-rec被销毁之后你就称之为.Common Lisp对此没有任何警告,因为它希望您稍后将全局定义它.它不会与您不使用的范围进行比较.

通过移动结束括号,以便my-replace-reclabelsemacs中完成调用将正确识别代码:

(defun  my-replace (e1 e2 L)
  "Perform a deep replace e1 with e2 in L."
  (labels ((my-replace-rec (e1 e2 L)
              "Used for recursion"
              (cond ((endp L) nil)
                    ((equal (car L) e1) (cons e2 (cdr L)))
                    ((listp (car L)) (my-replace-rec e1 e2 (car L)))
                    (t (my-replace-rec e1 e2 (cdr L))))))
    (my-replace-rec e1 e2 L)))
Run Code Online (Sandbox Code Playgroud)

现在,当你查看你的代码时,它看起来与此相同,因为你已经将它看作my-replace-rec是在标签中使用它,而编辑器和你的实现知道它不是.