有时我会在我的lisp代码中使用if语句层。这样做还有其他选择吗?
答案 0 :(得分:4)
这是其中一个案例,不幸的是,答案是“它取决于”。在某些情况下,显而易见的选择是使用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
形式也不够清晰,在这种情况下,通常值得盯着实际问题稍微努力一点。可能有一种方法可以更好地分解逻辑(调度表,外部逻辑调用具有合适参数的函数,......)。
答案 1 :(得分:2)
您可以通过几个方向更改代码。
创建封装条件的高阶函数,或者可能是宏,或者可能重用现有的宏(例如,查看at case macro)。 remove-if
将是一个高阶函数的示例,可以帮助您编写“if”。
使用多态。 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.
换句话说,通过封装状态,您可以避免显式写入条件语句。你也可以在途中获得一些可读性,因为你不需要记住列表中的哪一部分包含哪些信息 - 你现在可以将它标记为“名称”。