LISP - append Method Combination
CLOS Method Combination: The append Type
Section titled “CLOS Method Combination: The append Type”Method combination is a cornerstone of the Common Lisp Object System (CLOS), allowing developers to define how methods from different classes in a hierarchy should work together. While standard method combination (:around, :before, :after) is the most common, CLOS provides other built-in types for specialized tasks. This tutorial focuses on the append method combination, used for collecting results from multiple methods into a single list.
What is append Method Combination?
Section titled “What is append Method Combination?”When you specify :method-combination append for a generic function, CLOS changes how it executes applicable methods. Instead of the standard hierarchy, it does the following:
- It calls all applicable primary methods for a given set of arguments.
- It expects each method to return a list.
- It concatenates all these lists together using the
appendfunction to produce the final result.
This is extremely useful for scenarios where different parts of your system need to contribute items to a collection, such as gathering permissions, features, or configuration values.
Practical Example: Gathering User Permissions
Section titled “Practical Example: Gathering User Permissions”Let’s model a system where a user can have multiple roles, and each role grants a set of permissions. We want a function get-permissions that returns a complete list of all permissions for a user.
Step 1: Define Classes
Section titled “Step 1: Define Classes”(defclass user () ())
(defclass guest (user) ())
(defclass editor (user) ())
(defclass administrator (editor) ; An admin is also an editor ())Step 2: Define the Generic Function with append
Section titled “Step 2: Define the Generic Function with append”;; Define a generic function that will use the 'append' method combination.(defgeneric get-permissions (user) (:method-combination append))Step 3: Define Methods for Each Role
Section titled “Step 3: Define Methods for Each Role”Each method is specialized for a user class and returns a list of permissions associated with that role. Note the append keyword after the function name in defmethod.
;; Every user, even a guest, can view content.(defmethod get-permissions append ((user guest)) (list :view-content))
;; An editor can also create and edit posts.(defmethod get-permissions append ((user editor)) (list :create-post :edit-post))
;; An administrator has the highest level of permissions.(defmethod get-permissions append ((user administrator)) (list :delete-user :manage-system))Putting It All Together and Testing
Section titled “Putting It All Together and Testing”Because of multiple inheritance and method combination, calling get-permissions on an instance of a class will trigger all relevant methods in its hierarchy, and append will collect the results.
Code: main.lisp
Section titled “Code: main.lisp”;; Create instances of our user types(let ((guest-user (make-instance 'guest)) (editor-user (make-instance 'editor)) (admin-user (make-instance 'administrator)))
(format t "Guest permissions: ~s~%" (get-permissions guest-user))
(format t "Editor permissions: ~s~%" (get-permissions editor-user))
(format t "Admin permissions: ~s~%" (get-permissions admin-user)))Output
Section titled “Output”Guest permissions: (:VIEW-CONTENT)Editor permissions: (:CREATE-POST :EDIT-POST :VIEW-CONTENT)Admin permissions: (:DELETE-USER :MANAGE-SYSTEM :CREATE-POST :EDIT-POST :VIEW-CONTENT)Explanation
Section titled “Explanation”The output for the administrator demonstrates the power of this technique. An administrator inherits from editor, which inherits from user (and implicitly guest in our setup). CLOS calls the methods for all three classes, and the append combination neatly gathers all the permissions into one comprehensive list. The order of results depends on the Class Precedence List (CPL), which by default places the most specific class’s results first.
Other Built-in Method Combinations
Section titled “Other Built-in Method Combinations”CLOS offers other useful method combinations like + (sums numeric results), and (short-circuits on nil), or (short-circuits on non-nil), and list (collects results into a list of lists). Choosing the right combination type can greatly simplify your code.