Common-LISP调试(包含代码)

时间:2015-05-05 10:53:46

标签: debugging lisp common-lisp

我希望快速修复我的代码,该代码会接收一个数字列表,数字列表和一个阈值,并返回numberlist中大于阈值的项目数。我只是无法弄清楚出了什么问题,而且我对调试并不熟悉。我是stackoverflow和LISP的新手......我们欢迎任何评论/批评/建议。谢谢!

ex)(count-greater-than(list 1 2 3 4 5 6 6 7)5)=> 3

(defun count-greater-than (numberlist threshold)
  (if (null numberlist) 0
    (counter (numberlist threshold 0)))
  (defun counter (numberlist threshold count)
    (cond ((null numberlist) count)
          ((> (first numberlist) threshold) (counter (rest numberlist) threshold (+ 1 count)))
          (t (counter (rest numberlist) threshold count)))))

1 个答案:

答案 0 :(得分:2)

首先,请注意标准实际上包含的功能可以帮助完成这样的事情。有一个有用的 count-if 函数可以获取谓词并计算列表中有多少元素满足它。对于您的情况,您可以这样做:

CL-USER> (count-if #'(lambda (x)
                       (> x 5))
                   (list 1 2 3 4 5 6 6 7))
;=> 3

CL-USER> (defun count-greater-than (numbers threshold)
           (count-if (lambda (n) (> n threshold)) numbers))
COUNT-GREATER-THAN
CL-USER> (count-greater-than (list 1 2 3 4 5 6 6 7) 5)
3
CL-USER> (count-greater-than (list 1 2 3 4 5 6 6 7) 6)
1

在您的特定情况下,看起来您手动执行此操作,但您的括号错误。看起来您正在尝试创建一个名为计数器的本地帮助程序函数。您可以使用 defun 在函数外部定义它,例如:

(defun count-greater-than (numberlist threshold)
  (if (null numberlist) 0
    (counter (numberlist threshold 0))))

(defun counter (numberlist threshold count)
  (cond ((null numberlist) count)
        ((> (first numberlist) threshold) (counter (rest numberlist) threshold (+ 1 count)))
        (t (counter (rest numberlist) threshold count))))

或者您可以使用标签

以本地定义执行此操作
(defun count-greater-than (numberlist threshold)
  (labels ((counter (numberlist threshold count)
             (cond ((null numberlist) count)
                   ((> (first numberlist) threshold) (counter (rest numberlist) threshold (+ 1 count)))
                   (t (counter (rest numberlist) threshold count)))))
    (if (null numberlist) 0
        (counter numberlist threshold 0))))

备注

正如Xach在评论中指出的那样,你可以使用 count :test 参数更加简洁地做到这一点。我不知道它是否明确地捕捉了“用这个属性计算事物”的概念,但是它提供了一个非常短的解决方案:

CL-USER> (count 5 (list 1 2 3 4 5 6 6 7) :test #'<)
;=> 3

这计算列表中5的次数,但诀窍在于,不是使用 eql = 检查列表元素是否为5,而是使用<强>&LT; 即可。也就是说,计数最终将检查(&lt; 5 1),然后(&lt; 5 2),...,最多(&lt; 5 6)(&lt; 5 7) 指定使用该顺序的参数调用测试。 glossary entry on satisfy the test说(重点补充):

  
      
  1. (用于双参数测试)处于一种状态,使得作为序列函数的测试参数的双位谓词返回true   当第一个参数被认为是时,和   当给出第二个参数时,它是调用的结果   序列函数关于序列元素的关键参数   函数的序列参数正在测试是否相等;
  2.