我想解决一个返回NUMBER(计数)数字的lisp函数,这些数字大于列表中的第一个数字.列表是一个数字的线性列表.
(defun foo (lst)
(cond ((null lst) 0)
(car = k)
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
Run Code Online (Sandbox Code Playgroud)
我的问题是我不能保留第一个元素并将其与其他元素进行比较.
让我们解决你的问题:
你有一组数字.真的,你有一个"特殊"的第一个号码,然后是其余的号码.具体来说,您可能只想要实数,因为"小于"在复杂(虚数)数字方面没有意义.
您可以使用first从列表中获取第一个数字,以及rest其他数字.
其中,你想要计算任何不大于第一个的数.
所以让我们从一种伪代码开始吧
(defun count-numbers-greater-than-first (list)
;; split out first and rest
;; call the real count function
)
Run Code Online (Sandbox Code Playgroud)
好了,现在我们知道,我们可以使用first和rest(也,如您使用的,历史car和cdr),所以:
(defun count-numbers-greater-than-first (list)
(count-numbers-greater-than (first list) (rest list))
Run Code Online (Sandbox Code Playgroud)
您可能已经知道>用于测试实数是否大于彼此.
快速浏览CLHS可以看到一个很好的函数 count-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
Run Code Online (Sandbox Code Playgroud)
的???需要是一个对象function类型或功能的名称.我们需要将reference(第一个数字)"curry" 到该函数中.这意味着我们想要创建一个新函数,该函数仅用于一次运行count-if,已经"关闭"了它的值reference.
如果我们知道那number将永远是,那么100,该函数将如下所示:
(defun greater-than-100 (number)
(> number 100))
Run Code Online (Sandbox Code Playgroud)
然后可以在以下方面使用该函数count-if:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (function greater-than-100)
other-numbers))
(defun count-numbers-greater-than (reference other-numbers)
(count-if #'greater-than-100 other-numbers))
Run Code Online (Sandbox Code Playgroud)
但这并没有解决将reference数字"加入"函数的问题.
如果没有达到亚历山大(我稍后会解释),你可以使用lambda表格在这里创建一个新的匿名函数.既然reference可以在其中count-numbers-not-greater-than使用,您可以在其中使用其值lambda.让我们先转换为100:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number 100))
other-numbers))
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用reference:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number reference))
other-numbers))
Run Code Online (Sandbox Code Playgroud)
而且,实际上,如果您需要,您甚至可以将其合并到另一个函数中:
(defun count-numbers-greater-than-first (list)
(count-if (lambda (number) (> number (first list)))
(rest list)))
Run Code Online (Sandbox Code Playgroud)
但是,亚历山大呢?Alexandria是Quicklisp或其他地方提供的超级实用函数的集合.
(ql:quickload "alexandria")
(use-package #:alexandria)
Run Code Online (Sandbox Code Playgroud)
当然,你通常use是自己的defpackage
(defpackage my-cool-program
(:use :common-lisp :alexandria))
Run Code Online (Sandbox Code Playgroud)
它提供的东西有两个是curry和rcurry功能.事实证明,那里的lambda功能是一个非常普遍的情况.你有一个现有的函数 - 这里,>- 你想要反复调用相同的值,以及你想要每次传递的一些未知值.
最终看起来很像这样:
(lambda (x) (foo known x))
Run Code Online (Sandbox Code Playgroud)
您可以使用curry更简洁地编写相同的内容:
(curry #'foo known)
Run Code Online (Sandbox Code Playgroud)
它也适用于任何数量的参数.RCurry做同样的事情,但是它将未知值"x"放在左边,而你的已知值放在右边.
(lambda (x) (foo x known)) = (rcurry #'foo known)
Run Code Online (Sandbox Code Playgroud)
所以写另一种方法count-if是:
(defun count-numbers-greater-than-first (list)
(count-if (rcurry #'> (first list))
(rest list)))
* (count-numbers-greater-than-first '(10 9 8 7 11 12))
2
Run Code Online (Sandbox Code Playgroud)