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