はのは、あなたの問題を離れてみましょう。
あなたは数字のセットを持っています。本当に、あなたは「特別な」最初の数、および、それらの残りの部分を持っています。 「未満」は、複雑な(架空の)数字の面で意味がありませんので、具体的には、あなたはおそらく、実数のみをしたいです。
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で簡単に見はfunction
型のオブジェクト、または関数の名前であることをcount-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
???
ニーズと呼ばれる素敵な機能を明らかにする。その機能に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))
しかし、この関数に数字が「カリングされた」という問題を解決しません。
アレクサンドリアに到達せずに(私は瞬時に説明します)、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
あなたはこれまでに何をしようとしたのですか? – coredump
http://clhs.lisp.se/Body/f_countc.htm – coredump
(関数定義のFOO(LST) (COND ((ヌルLST)0) (車= K) ((>(カーLST)K) ()( (foo(cdr lst))))) – SomethingGeneral