まず、LET
or LET*
を使用してローカル変数を定義する必要があります。
(defun f (a b)
(let* ((c (* 4 a)) ; You need LET* instead of LET because
(d (* 2 (expt b 3))) ; RES depends on the previous variables.
(res (+ c d)))
(if (and (typep a 'integer) (typep b 'integer))
(list 'final 'value '= res)
'(your inputs are not numbers))))
実際の問題は、引数が整数であることを確認する前に計算を実行していることです。 IF
の内部で計算を移動する必要があります。
このようなリターンリストは奇妙なものです。ユーザーの出力としてそれらを出力する場合は、メッセージを印刷して実際の結果を返す必要があります。
(defun f (a b)
(if (and (integerp a) (integerp b))
(let ((result (+ (* 4 a)
(* 2 (expt b 3)))))
(format t "Final value = ~a~%" result)
result) ; Return RESULT or
(format t "Your inputs are not integers.~%"))) ; NIL from FORMAT.
ほとんどの場合、引数が正しいタイプでない場合は、エラーを通知する必要があります。計算を行う関数からの出力を印刷することは、通常、悪い考えです。
(defun f (a b)
(check-type a integer "an integer")
(check-type b integer "an integer")
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(handler-case
(format t "Final value = ~a~%" (f a b))
;; CHECK-TYPE signals a TYPE-ERROR if the type is not correct.
(type-error() (warn "Your inputs are not integers."))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; WARNING: Your inputs are not integers.
;=> NIL
Common Lisp条件システムでは、エラーを修正するために再起動を使用することもできます。 CHECK-TYPE
は、STORE-VALUE
という名前の再起動を確立します。この再起動を呼び出すと、その場所に正しい値を指定できます。この場合はおそらく意味をなさないでしょうが、デフォルトでは1
のようなことをすることができます。
(defun main (a b)
(handler-bind ((type-error (lambda (e)
(store-value 1 e))))
(format t "Final value = ~a~%" (f a b))))
(main 12 1)
; Final value = 50
;=> NIL
(main 12 'x)
; Final value = 50
;=> NIL
あなたがそれらを使用し、代わりに関数を呼び出す前に、あなたの引数をチェックしたくない場合がありますパフォーマンスの重要な機能のために条件/エラーハンドラは、いくつかのオーバーヘッドを追加しないことに注意してください。
(declaim (ftype (function (integer integer) integer) f))
(defun f (a b)
(declare (optimize (speed 3) (safety 0) (debug 0)))
(+ (* 4 a)
(* 2 (expt b 3))))
(defun main (a b)
(if (and (integerp a)
(integerp b))
(format t "Final value = ~a~%" (f a b))
(warn "Your inputs are not integers.")))
初心者からは、多くの助けがありました。あなたの貴重な材料に基づいて、私はさらに成長します。ありがとうございました。 –