1

有时,我的 lisp 代码中会出现多层 if 语句。有没有其他方法可以做到这一点?

4

2 回答 2

4

不幸的是,这是其中一种情况,答案是“视情况而定”。在某些情况下,显而易见的选择是使用cond.

(if condition1
   result1
   (if condition2
       result2
       default))

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

在其他时候,cond搭配一点orand可能正是您想要的。

(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 回答