首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套的“`defun`”在快板通用Lisp中产生重复警告

嵌套的“`defun`”在快板通用Lisp中产生重复警告
EN

Stack Overflow用户
提问于 2014-04-18 20:22:13
回答 2查看 741关注 0票数 3

在Common中,我有一个合并排序的通用实现:我有不同的拆分和合并函数的实现,对于拆分和合并函数的每一个组合,我想要构造一个合并排序函数。

  • 任何拆分函数都以字符串列表作为输入,并返回一个包含两个列表的列表:原始列表的两个部分。
  • 任何合并函数都以两个排序列表作为输入,并返回排序合并列表。

每个合并排序函数都是通过调用以下函数创建的:

代码语言:javascript
复制
(defun make-merge-sort-function (split-function merge-function)

  (defun merge-sort (lst)
    (if (or (null lst) (null (cdr lst)))
        lst
        (let ((s (funcall split-function lst)))
          (funcall merge-function (merge-sort (car s)) (merge-sort (cadr s))))))

  (lambda (lst)
    (merge-sort lst)))

我在merge-sort中定义了make-merge-sort-function,以保持其名称的私有性,并避免破坏名称空间。

我的代码使用几个通用Lisp实现(例如,Steel ):

  • 我所有测试运行的输出都进行了正确的排序,
  • 每个产生的合并排序函数都有不同的执行时间,表明使用了不同的拆分/合并组合。

所以,我假设我的代码是正确的。

但是,如果我使用快板通用Lisp运行程序,则会收到警告:

代码语言:javascript
复制
Warning: MERGE-SORT is defined more than once as `operator' in file foo.lisp.

其中foo.lisp是调用make-merge-sort-function的文件。因此,该程序运行良好,但在第一次调用之后,它会为每次调用make-merge-sort-function打印一次警告。如果我将merge-sort函数设置为全局函数(带有两个附加参数split-functionmerge-function),那么警告就会消失。

在快板公共Lisp中,我没有找到任何关于这个警告的含义的指示。我尝试过的其他实现(ABCL、CMUCL、CCL、CLISP、SBCL)不会发出任何警告。我认为可以多次定义内部函数(闭包)的新实例,我不明白为什么会出现问题。有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-18 21:06:39

您从不在公共Lisp中嵌套defun

就像在defun中使用defvar而不是defvar一样,您使用labels代替嵌套defun

代码语言:javascript
复制
(defun make-merge-sort-function (split-function merge-function)
  (labels ((merge-sort (lst)
             (if (or (null lst) (null (cdr lst)))
                 lst
                 (let ((s (funcall split-function lst)))
                   (funcall merge-function (merge-sort (car s)) 
                                           (merge-sort (cadr s)))))))
    #'merge-sort))
票数 4
EN

Stack Overflow用户

发布于 2014-05-01 07:13:14

您没有显示测试代码,因此,请考虑以下CLISP会话记录:

代码语言:javascript
复制
[3]> (defun make-merge-sort-function (split-function merge-function)
  (defun merge-sort (lst)
    (if (or (null lst) (null (cdr lst)))
        lst
        (let ((s (funcall split-function lst)))
          (funcall merge-function (merge-sort (car s))
                                  (merge-sort (cadr s))))))
  (lambda (lst)
    (merge-sort lst)))
MAKE-MERGE-SORT-FUNCTION
[4]> (fboundp 'merge-sort)
NIL                         <<---------------------------- NB
[5]> (defun sp1(x)(princ" IN SPL1 ") x)
SP1
[6]> (defun sp2(x)(princ" IN SPL2 ") x)
SP2
[7]> (defun mg1(x y)(princ" IN MRG1 ") x)
MG1
[9]> (setq f1 (make-merge-sort-function #'sp1 #'mg1))
#<FUNCTION :LAMBDA (LST) (MERGE-SORT LST)>
[10]> (fboundp 'merge-sort)
T                           <<---------------------------- NB !!
[12]> (funcall f1 '(1 2 3))
 IN SPL1                    <<---------------------------- NB
*** - CDR: 1 is not a list
[14]> (setq f2 (make-merge-sort-function #'sp2 #'mg1))
#<FUNCTION :LAMBDA (LST) (MERGE-SORT LST)>
[15]> (funcall f1 '(1 2 3))
 IN SPL2                    <<---------------------------- NB !!!
*** - CDR: 1 is not a list

现在您可以看到,您的代码所做的事情与您所认为的不同,您的测试代码可能没有将问题排除在外。

显然,嵌套的defun定义了一个全局访问的函数merge-sort,而第二次调用make-merge-sort-function则重新定义了它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23161698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档