讓我們拆開你的問題:
你有一組數字。真的,你有一個「特殊」的第一個號碼,然後是其他的。具體而言,您可能只需要實數,因爲「小於」在複數(虛數)方面沒有意義。
您可以使用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
(第一個數字)「咖喱」到該函數中。這意味着我們要創建一個新函數,該函數僅用於通過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))
但是,並沒有解決將「curried」號碼變成功能的問題。
沒有到達亞歷山大(我會在稍後解釋),您可以使用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)))
那個亞歷山大的東西
但是,亞歷山大呢?亞歷山大是在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
那你試試這麼遠嗎? – coredump
http://clhs.lisp.se/Body/f_countc.htm – coredump
(defun定義FOO(LST) (COND ((空LST)0) (汽車= K) ((>(汽車LST)k)的(1+(foo(cdr lst)))) (T (foo(cdr lst))))) – SomethingGeneral