基本 LISP 递归,枚举大于 3 的值

发布于 2024-10-03 02:24:19 字数 357 浏览 4 评论 0原文

我需要一个递归 LISP 函数来枚举任意数字列表中的元素数量 > 3.我不允许使用let、loops或while,只能使用基本的CAR、CDR、SETQ、COND、CONS、APPEND、PROGN、LIST...

这是我对函数的尝试:

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

I need a recursive LISP function that enumerates the number of elements in any list of numbers > 3. I'm not allowed to use lets, loops or whiles and can only use basic CAR, CDR, SETQ, COND, CONS, APPEND, PROGN, LIST...

This is my attempt at the function:

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

The function call:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等待圉鍢 2024-10-10 02:24:19

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

对于空列表,您返回空列表。所以如果你有列表(6),你将6添加到空列表的foo中,这就是空列表。这不起作用,因为您无法将号码添加到列表中。

lst 为空时,您可以通过使 foo 返回 0 而不是 lst 来轻松修复此问题。

作为风格注释:像这样混合 condif 似乎有点多余。我会这样写,只使用 cond 代替:

(defun foo (lst) 
  (cond
    ((null lst)
      0)
    ((> (car lst) 3) 
      (1+ (foo (cdr lst))))
    (T
      (foo (cdr lst)))))

Your code is pretty close to correct, just a small mistake in the base case:

For the empty list you return the empty list. So if you have the list (6), you add 6 to foo of the empty list, which is the empty list. That does not work because you can't add a number to a list.

You can easily fix it by making foo return 0 instead of lst when lst is empty.

As a style note: Mixing cond and if like this, seems a bit redundant. I would write it like this, using only cond instead:

(defun foo (lst) 
  (cond
    ((null lst)
      0)
    ((> (car lst) 3) 
      (1+ (foo (cdr lst))))
    (T
      (foo (cdr lst)))))
っ〆星空下的拥抱 2024-10-10 02:24:19

一些风格要点:

  • 没有必要将一些 Lisp 内置函数变成大写。现在已经不是1958年了!
  • 但是,如果您要将内置函数设置为大写,为什么不使用 DEFUNNULL 呢?
  • 您的 cond 的最后一个分支中有一个 if。这是多余的。既然cond的目的是测试条件,为什么不使用它呢?
  • 无需像这样将右括号隔开。现在没有人计算括号了,我们有括号匹配编辑器。
  • Lisp 对函数和值有单独的命名空间,因此您不必调用参数 lst 以避免与内置函数 list 发生冲突。

如果您是真实编程,那么您当然会使用 count-如果

(count-if #'(lambda (x) (> x 3)) '(0 1 2 3 4 5 6))
    ==> 3

Some stylistic points:

  • There's no need to put some Lisp built-ins in uppercase. It's not 1958 anymore!
  • But if you are going to put built-ins in uppercase, why not DEFUN and NULL?
  • You have an if inside the last branch of your cond. This is redundant. Since the purpose of cond is testing conditions, why not use it?
  • There's no need to space out your closing parentheses like that. No-one counts parentheses these days, we have parenthesis-matching editors.
  • Lisp has separate namespaces for functions and values, so you don't have to call your argument lst to avoid conflicting with the built-in function list.

If you were programming this for real, of course you'd use count-if:

(count-if #'(lambda (x) (> x 3)) '(0 1 2 3 4 5 6))
    ==> 3
做个ˇ局外人 2024-10-10 02:24:19

您可以在重复递归调用时进行一项保存:

(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

One save you can have on duplication of the recursive call:

(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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文