有时,我的 lisp 代码中会出现多层 if 语句。有没有其他方法可以做到这一点?
问问题
131 次
2 回答
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
形式也不够清晰,在这种情况下,通常值得更加努力地关注实际问题。可能有一种更好的方式分解逻辑的方法(调度表,具有合适参数的外部逻辑调用函数,......)。
于 2012-09-27T14:00:06.030 回答
2
您可以更改代码的方向很少。
创建封装条件的高阶函数,或者可能是宏,或者可能重用现有的宏(例如看一下 case 宏)。
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.
换句话说,通过封装状态,您可以避免显式编写条件语句。在此过程中,您还将获得一些可读性,因为您不需要记住列表的哪一部分包含哪些信息 - 您现在将其标记为“名称”。
于 2012-09-27T14:46:24.657 回答