1

ときどき、自分の Lisp コードに if ステートメントの層ができてしまうことがあります。これを行う代わりの方法はありますか?

4

2 に答える 2

4

残念ながら、答えが「場合による」であるケースの 1 つです。場合によっては、当然の選択は を使用することcondです。

(if condition1
   result1
   (if condition2
       result2
       default))

;; naturally converted to:
(cond (condition1 result1)
      (condition2 result2)
      (t default))

他の時にcondは、ちょっとしたものと組み合わせたり、orまさにandあなたが望むものかもしれません.

(if condition1
   (if condition2
       result12
       result1)
   (if condition2
       result2
       default))

;; naturally turns intoteh answe
(cond ((and condition1 condition2) result12)
      (condition1 result1)
      (condition2 result2)
      (t default))

注意、私はこのコードをテストせずに書いただけですが、原則として問題ないはずです。

残念ながら、多少読みやすいcond形式でも十分に明確でない場合があり、そのような場合は通常、実際の問題をもう少し詳しく調べる価値があります。より良い方法でロジックを分解する方法があるかもしれません (ディスパッチ テーブル、適切なパラメーターで関数を呼び出す外部ロジックなど)。

于 2012-09-27T14:00:06.030 に答える
2

コードを変更するために移動できる方向はほとんどありません。

  1. 条件をカプセル化する高次関数を作成するか、おそらくマクロを作成するか、既存のマクロを再利用します (たとえば、case マクロを見てください)。remove-if「if」の記述を省くことができる高次関数の例になります。

  2. ポリモーフィズムを使用します。Lisp には、クラス、オブジェクト、オーバーロード、およびオブジェクト システムに必要なすべての計測器があります (おそらく少し余分なものもあります ;)。

次のコードがあるとします。

;; Suppose your `person' is a list that has that person's
;; name as its first element:

(defun hello! (person)
  (if (string= (car person) "John")
        (concatenate 'string "Hello, " (car person))
     (print "Hello, who are you?")))

(defun goodbye! (person)
  (if (string= (car person) "John")
        (concatenate 'string "Goodbye, " (car person))
     (print "Goodbye, mysterious stranger!")))

;; You would use it like so:
(hello! '("John" x y z))
(goodbye! '(nil x y z))

これで、次のように書き換えることができます。

(defclass person () ())

(defclass friend (person)
  ((name :accessor name-of
         :initarg :name)))

(defgeneric hello! (person))
(defgeneric goodbye! (person))

(defmethod hello! ((person person))
  (print "Hello, who are you?"))

(defmethod hello! ((person friend))
  (print (concatenate 'string "Hello, " (name-of person))))

(defmethod goodbye! ((person person))
  (print "Goodbye, mysterious stranger!"))

(defmethod goodbye! ((person friend))
  (print (concatenate 'string "Goodbye, " (name-of person))))

;; Which you would use like so:

(hello! (make-instance 'person))
(goodbye! (make-instance 'friend :name "John"))

;; Note that however the later is significantly more verbose
;; the ratio will change when you have more `if's which you
;; can systematize as objects, or states.

つまり、状態をカプセル化することで、条件ステートメントを明示的に記述することを回避できます。また、リストのどの部分にどのような情報が含まれているかを覚える必要がないため、途中で読みやすくなります。これで、「名前」というラベルが付けられます。

于 2012-09-27T14:46:24.657 に答える