LISP - `append` 方法组合
CLOS 方法组合:append 类型
Section titled “CLOS 方法组合:append 类型”方法组合是 Common Lisp 对象系统 (CLOS) 的基石,它允许开发人员定义层次结构中不同类的方法应如何协同工作。虽然标准方法组合 (standard method combination)(:around、:before、:after)最为常见,但 CLOS 也提供了其他内置类型用于特殊任务。本教程重点介绍 append 方法组合,它用于将多个方法的结果收集到一个列表中。
什么是 append 方法组合?
Section titled “什么是 append 方法组合?”当您为泛型函数指定 :method-combination append 时,CLOS 会改变其执行适用方法的方式。与标准层次结构不同,它会执行以下操作:
- 它调用给定一组参数的所有适用的主方法。
- 它期望每个方法都返回一个列表。
- 它使用
append函数将所有这些列表连接起来,以生成最终结果。
这对于系统中不同部分需要向集合贡献项的场景非常有用,例如收集权限、功能或配置值。
实际示例:收集用户权限
Section titled “实际示例:收集用户权限”让我们来建模一个系统,其中用户可以拥有多个角色,并且每个角色授予一组权限。我们希望有一个函数 get-permissions,它返回用户所有权限的完整列表。
步骤 1:定义类
Section titled “步骤 1:定义类”(defclass user () ())
(defclass guest (user) ())
(defclass editor (user) ())
(defclass administrator (editor) ; An admin is also an editor ())步骤 2:使用 append 定义泛型函数
Section titled “步骤 2:使用 append 定义泛型函数”;; 定义一个将使用 'append' 方法组合的泛型函数。(defgeneric get-permissions (user) (:method-combination append))步骤 3:为每个角色定义方法
Section titled “步骤 3:为每个角色定义方法”每个方法都针对用户类进行了特殊化,并返回与该角色关联的权限列表。请注意 defmethod 中函数名后面的 append 关键字。
;; 每个用户,甚至是访客,都可以查看内容。(defmethod get-permissions append ((user guest)) (list :view-content))
;; 编辑者也可以创建和编辑帖子。(defmethod get-permissions append ((user editor)) (list :create-post :edit-post))
;; 管理员拥有最高级别的权限。(defmethod get-permissions append ((user administrator)) (list :delete-user :manage-system))由于多重继承和方法组合,对类的实例调用 get-permissions 将触发其层次结构中所有相关方法,并且 append 将收集结果。
代码:main.lisp
Section titled “代码:main.lisp”;; 创建我们的用户类型实例(let ((guest-user (make-instance 'guest)) (editor-user (make-instance 'editor)) (admin-user (make-instance 'administrator)))
(format t "访客权限:~s~%" (get-permissions guest-user))
(format t "编辑者权限:~s~%" (get-permissions editor-user))
(format t "管理员权限:~s~%" (get-permissions admin-user)))Guest permissions: (:VIEW-CONTENT)Editor permissions: (:CREATE-POST :EDIT-POST :VIEW-CONTENT)Admin permissions: (:DELETE-USER :MANAGE-SYSTEM :CREATE-POST :EDIT-POST :VIEW-CONTENT)管理员的输出展示了这种技术的强大之处。一个 administrator 继承自 editor,而 editor 又继承自 user(在我们的设置中隐式地继承自 guest)。CLOS 会调用所有三个类的相应方法,并且 append 组合巧妙地将所有权限收集到一个综合列表中。结果的顺序取决于类优先级列表 (Class Precedence List, CPL),该列表默认将最具体的类的结果放在前面。
其他内置方法组合
Section titled “其他内置方法组合”CLOS 还提供了其他有用的方法组合,例如 +(对数值结果求和)、and(遇到 nil 短路)、or(遇到非 nil 短路)和 list(将结果收集到列表的列表中)。选择正确的方法组合类型可以大大简化您的代码。