-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmethod-combinations.lisp
69 lines (64 loc) · 3.04 KB
/
method-combinations.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(in-package #:method-combination-utilities)
(define-method-combination primary ()
((primary () :required t))
"This simple method combination requires that no methods have any qualifiers.
Methods are treated exactly like primary methods in the STANDARD method
combination."
`(call-method ,(first primary) ,(rest primary)))
(define-method-combination lax ()
((around (:around . *))
(before (:before . *))
(after (:after . *) :order :most-specific-last)
(primary * :required t))
"This combination allows (and ignores) additional method qualifiers after any
of the `STANDARD` qualifiers. It is useful if you are handling your
qualifiers in a custom method class."
(combine-standard-methods primary around before after))
(define-method-combination basic
(operator
&optional identity-with-one-argument-p (order :most-specific-first))
((around (:around))
(before (:before))
(after (:after))
(primary (*) :order order :required t))
"This combination removes the need for the built-in combinations (other than
STANDARD) and the short form of DEFINE-METHOD-COMBINATION.
Differences from old built-in usage:
* specify as '(basic progn t :most-specific-last) instead of
'(progn :most-specific-last)
* can specify an arbitrary operator without having to first
DEFINE-METHOD-COMBINATION
* IDENTITY-WITH-ONE-ARGUMENT[-P] is now specified at usage rather than
definition
* :BEFORE and :AFTER methods are allowed."
(let ((invalid-method (find-if-not (lambda (qualifiers)
(equal (list operator) qualifiers))
primary
:key #'method-qualifiers)))
(when invalid-method
(error "~S is an invalid method.~@
Its qualifier must be either :AROUND or ~S."
invalid-method operator)))
(wrap-primary-form (if (or (not identity-with-one-argument-p) (rest primary))
`(,operator ,@(call-methods primary))
`(call-method ,(first primary)))
around
before
after))
(define-method-combination append/nconc (&optional order)
((around (:around))
(primary (append) (nconc) :order order :required t))
"This is an improvement on the built-in APPEND method combination, which uses
the short form of DEFINE-METHOD-COMBINATION. This allows either `NCONC` or
`APPEND` to be used as a qualifier depending on whether or not the method
returns a list where the last cons can be modified. If all but the last
primary methods specify `NCONC`, then `NCONC` will be used, otherwise,
`APPEND`."
(wrap-primary-form (if (rest primary)
`(,(if (find '(append) (butlast primary)
:test #'equal :key #'method-qualifiers)
'append
'nconc)
,@(call-methods primary))
`(call-method ,(first primary)))
around))