2017-02-07 6 views
0

これは私のリスプコードです。Lisp - if文さまざまなアクション

(DEFUN F (A B) 
       (SETF C (* 4 A)) 
       (SETF D (* 2 (EXPT B 3))) 
       (SETF RES (+ C D)) 
       (IF (AND (TYPEP A 'INTEGER) (TYPEP B 'INTEGER)) 
        (list 'Final 'value '= res) 
       '(YOUR INPUTS ARE NOT NUMBERS))) 

たとえば、(f 5 9)はうまくいきます。 しかし、次のエラーメッセージで(f 'w 'q)は動作しません:私は、Aは、Bが整数4A + 2B^3を計算した場合にしたい

(ERROR TYPE-ERROR DATUM W EXPECTED-TYPE NUMBER FORMAT-CONTROL [email protected]< ~s' is not of the expected type ~s'~:@> FORMAT-ARGUMENTS (W NUMBER)) Error: W' is not of the expected type NUMBER'

これ以外の場合は、少なくとも1つが整数の印刷エラーメッセージではない場合。

私は上記のコードを試してみます。 しかし、if文を使用してこのエラー処理を行うにはどうすればよいですか?

答えて

5

まず、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."))) 
+0

初心者からは、多くの助けがありました。あなたの貴重な材料に基づいて、私はさらに成長します。ありがとうございました。 –

関連する問題