4

我需要一个递归 LISP 函数,它枚举任何大于 3 的数字列表中的元素数。我不允许使用 let、循环或 while,只能使用基本的 CAR、CDR、SETQ、COND、CONS、APPEND、PROGN , 列表...

这是我对该功能的尝试:

(defun foo (lst) 
  (COND ((null lst) lst) 
    (T (IF (> (CAR lst) 3) 
      (1+ (foo (CDR lst)))
      (foo (CDR lst)) ) ) ) )

函数调用:

(foo '(0 1 2 3 4 5 6))
4

3 回答 3

5

一些风格点:

  • 没有必要将一些 Lisp 内置函数以大写形式放置。现在已经不是 1958 年了!
  • 但是,如果您要将内置函数以大写形式显示,为什么不使用DEFUNandNULL呢?
  • 你有一个在你if的最后一个分支里面cond。这是多余的。既然目的cond是测试条件,为什么不使用呢?
  • 没有必要像这样隔开你的右括号。这些天没有人计算括号,我们有括号匹配的编辑器。
  • Lisp 对函数和值有单独的命名空间,所以你不必调用你的参数lst来避免与内置函数冲突list

如果你是真的编程,当然你会使用count-if

(count-if #'(lambda (x) (> x 3)) '(0 1 2 3 4 5 6))
    ==> 3
于 2010-11-18T22:55:44.143 回答
5

您的代码非常接近正确,只是基本情况下的一个小错误:

对于空列表,您返回空列表。因此,如果您有 list (6),则将 6 添加到foo空列表,即空列表。这不起作用,因为您无法将数字添加到列表中。

您可以通过fooreturn0而不是lstwhenlst为空来轻松修复它。

作为风格说明:混合condif这样,似乎有点多余。我会这样写,只使用cond

(defun foo (lst) 
  (cond
    ((null lst)
      0)
    ((> (car lst) 3) 
      (1+ (foo (cdr lst))))
    (T
      (foo (cdr lst)))))
于 2010-11-18T22:44:59.323 回答
0

递归调用的重复可以节省一个:

(defun foo (l)
  (if (null l) 0               ; if list is empty, return 0
    (+ (if (> (car l) 3) 1 0)  ; else +1 if condition is satisfactory
      (foo (cdr l)))))         ; plus the result from the rest
于 2018-09-11T01:11:16.650 回答