【问题标题】:Common-LISP debugging (code included)Common-LISP 调试(包含代码)
【发布时间】:2015-05-05 10:53:45
【问题描述】:

我希望快速修复我的代码,该代码接受数字列表、数字列表和阈值,并返回数字列表中大于阈值的项目数。我就是不知道出了什么问题,而且我对调试也不熟悉。我对stackoverflow很陌生,一般来说LISP......任何cmets /批评/建议都将受到欢迎。谢谢!

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

【问题讨论】:

  • 检查括号。只有一个顶级函数,而另一个函数以某种方式包含在第一个函数中?这看起来很奇怪。创建两个独立的函数。
  • @RainerJoswig 我想知道是否打算创建一个本地递归函数,例如,使用 labels
  • @RainerJoswig 谢谢。我才意识到这就是问题所在;现在它正在工作。谢谢! (如何将这个问题称为“已解决”?)

标签: debugging lisp common-lisp


【解决方案1】:

首先,请注意该标准实际上包含有助于解决此类问题的功能。有一个有用的 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

在您的特定情况下,您似乎是手动执行此操作,但括号错误。您似乎正在尝试创建一个名为 counter 的本地辅助函数。您可以使用 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 在 cmets 中指出的那样,您实际上可以使用 count:test 参数更简洁地做到这一点。我不知道它是否非常明确地捕捉到“用这个属性计算事物”的概念,但它提供了一个非常简短的解决方案:

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

这会计算 5 在列表中出现的次数,但诀窍是它不是使用 eql= 检查列表元素是否为 5,而是使用 。也就是说,count 最终会检查 (,然后是 (,...,直到 ( 、(。 is 指定测试将按该顺序使用参数调用。 glossary entry on satisfy the test 说(强调):

  1. (对于两个参数测试)处于这样一种状态,即作为序列函数的测试参数的两位谓词返回 true 当给定作为被考虑对象的第一个参数时,并且 当给定 第二个参数时,该参数是调用 序列函数在序列元素上的关键参数 正在测试是否相等的函数的序列参数

【讨论】:

  • 这很有帮助!只是我正在上一门介绍性的 AI 课程,而且我只被允许使用很少的原语。我还没学过lamda。谢谢你也教我如何使用标签!
  • @Shauny 嗯,该站点通常面向“专业和狂热的程序员”,所以总的来说,他们更喜欢 count-if(没有理由重新发明轮子毕竟)。询问家庭作业、练习等并没有错,但在问题中提及任何人为限制通常被认为是一种礼貌,因为默认情况下,答案会寻找“典型”的做事方式。跨度>
  • 我会选择 (count 5 list :test #'
  • @Xach 非常好(我会将其添加到答案中),但它对“用属性计算事物”的性质不太明确。在我看来,它最大的问题是你必须记住测试将通过什么顺序传递它的参数。即,对于列表中的每个 x,将调用 (
  • 一般来说,你必须记住很多东西才能使用 CL。
猜你喜欢
  • 1970-01-01
  • 2011-09-05
  • 2013-12-03
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2013-08-08
  • 2011-12-24
  • 1970-01-01
相关资源
最近更新 更多