【问题标题】:Lisp labels function deleted before usedLisp 标签函数在使用前被删除
【发布时间】:2017-09-27 20:55:27
【问题描述】:

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

(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))

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

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

; Warning: This function is undefined:                                          
;   MY-REPLACE-REC

我试图尽可能多地适应错误消息,但我正在使用 Emacs(我还是个新手)并试图从一个小缓冲区中粘贴出来。

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

【问题讨论】:

    标签: function lisp common-lisp


    【解决方案1】:

    您的缩进已关闭。这是正确缩进的代码:

    (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))
    

    labelslet 一样工作。您需要在 labels 的主体中使用创建的对象,而不是在函数被销毁之后。

    用让:

    (let ((a 10))
      ; a exists here
      )
    ; a doesn't exist anymore
    

    labels

    (labels ((name (arg) arg))
      ; the function exists here
      )
    ;the function doesn't esist anymore
    

    在您的代码中创建my-replace-rec,然后在标签正文中什么都不做,在my-replace-rec 被销毁后,您调用它。 Common Lisp 对此没有任何警告,因为它希望您稍后将在全局范围内定义它。它不会将它与您碰巧不使用的范围进行比较。

    通过移动结束括号,以便在 labels 中完成对 my-replace-rec 的调用,emacs 将正确识别代码:

    (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)))
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多