あなたcond
が不適切に構築され、コードの不必要な副作用を生成するビットで中置記法に切り替え、count-numbers
. 仮説的には、実行された場合、そのエラーはほぼ正しいように聞こえます。パラメータで数値比較を行っています(および数値以外の入力でのエラー)。
今日はコードレビューの帽子をかぶったので、これをもう少し詳しく説明しましょう。
Lisp (これは CL、Scheme、およびすべての雑種に適用されます) は変数名や関数名でlower-case-snake-case-with-dashes
はなく、 を使用します。lowerCamelCase
(defun is-num (n)
(and (<= n 9) (>= n 0)))
Common Lisp の慣習は、述語をで始めるのではなくp
orで終わらせることです。スキームには、代わりに述語を終了する(IMOの方が良い)規則があります-p
is-
?
(defun num-p (n)
(and (<= n 9) (>= n 0)))
((and (<= N 9) (>= N 0)))
関数を呼び出す方法ではありません。本体を呼び出そうとするだけでなく、実際にその名前を使用する必要があります。これは、このコードを実行しようとした場合に発生する多くのエラーの 1 つの原因です。
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond
((null list) nil)
((num-p item) item)(incf count))
(setq(0 + count))))))
numberp
既に存在し、数値比較を試みるのではなく、その入力に対して型チェックを行います。おそらく代わりにそれを使用する必要があります。
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond
((null list) nil)
((numberp item) item)(incf count))
(setq(0 + count))))))
((numberp item) item) (incf count))
cond
おそらく、それが句として行うと思っていることを行いません。実際には、2 つの別個の節として扱われます。item
が であるかどうかをチェックnumber
し、そうである場合はそれを返します。2番目は変数をチェックしようとし、評価された場合にincf
戻ります(評価されず、評価されません)。あなたが望んでいるように見えるのは、リストに数字が見つかったときにカウンターをインクリメントすることです。つまり、その句を.count
t
count
incf
item
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond ((null list) nil)
((numberp item)
(incf count)
item))
(setq (0 + count)))))
(setq (0 + count))
3つの理由で間違っている
- 中置記法に戻ったようです。つまり、2 番目のビットが実際に
0
変数+
をcount
引数として関数を呼び出そうとしていることを意味します。
- の 2 番目の部分がありません
setq
。つまり、上記をNIL
暗黙的に に設定しようとしています。
- 値を返すために実際に何も設定する必要はありません
この時点で、最終的に評価されて適切に実行されるコードが完成しました (そして、上記のエラーをスローしません)。
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond ((null list) nil)
((numberp item)
(incf count)
item))
count)))
dolist
指定されたリスト内の各要素に対して何かを行う反復構造です。つまり、リストの終了を実際に手動でテストする必要はありませんcond
。また、dolist
結果を収集しないため、それに戻る理由はありませんitem
。count
また、で宣言した local を不必要にシャドウイングしていますlet
。
(defun count-numbers (list)
(let ((count 0))
(dolist (item list)
(when (numberp item) (incf count)))
count))
いつものように、これらすべてをより簡単なloop
呼び出しで行うことができます。
(defun count-numbers (list)
(loop for item in list
when (numberp item) sum 1))
これにより、カウンターが暗黙的になり、手動で返す必要がなくなります。実際、これが特に独自の反復関数を作成する演習でない限り、Common Lisp には組み込みの がありcount-if
、これはその match内の項目predicate sequence [some other options]
の を受け取って返します。スタイル上の理由で具体的に名前を付けたい場合は、count
sequence
predicate
count-numbers
(defun count-numbers (list) (count-if #'numberp list))
そしてそれで終わります。
結論としては、良い試みですが、さらなる質問をする前に言語ファミリーを読んでみてください。