【问题标题】:Why does replacing "(null x)" with "(null (cdr x))" make this code work?为什么用“(null(cdr x))”替换“(null x)”会使这段代码工作?
【发布时间】:2014-05-29 08:06:54
【问题描述】:

我是 LISP 的新手。我正在尝试在 LISP 中编写冒泡排序函数。

这是我到目前为止所做的。

(defun mysort (x)
  (if (null  x) x
    (if (< (car x) (cadr x))
     (cons (car x) (mysort (cdr l)))
     (cons (cadr x) (mysort (cons (car x) (cddr x)))))))

我遇到了一个错误

NIL is not a real number

当我修改代码时(参考了几个代码后)-

(defun mysort (x)
  (if (null  (cdr x)) x
   (if (< (car x) (cadr x))
    (cons (car x) (mysort (cdr l)))
    (cons (cadr x) (mysort (cons (car x) (cddr x)))))))

现在可以正常使用了。

为什么要替换 (如果 (null x) x...) 和 (如果 (null (cdr x)) x...) 有所作为?

另外,我从另一个函数调用 mysort 来运行它(长度 x)次数。是否有可能在一个递归循环中,只使用基本函数就可以实现完整的排序?

【问题讨论】:

  • 在工作/失败情况下(cdr x) 是什么?这与使用/返回的x 有何关系?想象一下,当 x 是 '(a)/(cons 'a nil)'()/nil 时。
  • 哦,现在知道了。感谢您的帮助。

标签: lisp common-lisp


【解决方案1】:

如果要查看第一个元素是否小于第二个元素,那么列表需要至少有两个元素。

如果只有一个元素,CADR 返回NIL。这不是一个数字。

CL-USER 18 > (cadr '(1))
NIL

您的 Lisp 系统不仅应该告诉您错误,还应该告诉您发生错误的函数。这里:函数&lt;

使用(null (cdr list)) 是测试是否有第二个元素的好方法。一个典型的错误是调用LENGTH,这是低效的。

【讨论】:

    【解决方案2】:

    要进行比较,您至少需要两个元素,因此检查 x 是否为 NIL 是不够的。

    检查(cdr x) 是否为NIL 是检查列表长度是否至少为两个的好方法,因为NIL 是特殊的,即使它不是一个缺点单元格,也可以保证(cdr NIL)NIL .

    您遇到的错误是因为NIL 不是数字,因此您无法将其与&lt; 进行比较,并且在执行(&lt; (car x) (cadr x)) 时发生这种情况,而x 是具有单个元素的列表。

    关于在单个递归调用中进行排序,您可以使用以下排序定义:

    • 空列表已排序
    • 如果第一个元素是列表的最小值并且列表的其余部分已排序,则对非空列表进行排序。

    这导致

    (defun mysort (x)
      (if x
          (let ((minimum (reduce #'min x)))
            (cons minimum
                  (mysort (remove minimum x :count 1))))))
    

    顺便说一下,这是一种非常低效的排序方式。

    【讨论】:

      猜你喜欢
      • 2017-04-02
      • 2019-12-17
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多