Skip to content

Instantly share code, notes, and snippets.

@fiddlerwoaroof
Created May 21, 2017 07:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fiddlerwoaroof/c3e62bbe80ad345faa679f3b73be6eec to your computer and use it in GitHub Desktop.
Save fiddlerwoaroof/c3e62bbe80ad345faa679f3b73be6eec to your computer and use it in GitHub Desktop.
Isolate a Method in a Combined Method
(defmacro methodcall ((name &rest qualifiers-and-args) (&rest arg-values) &body next-function-body)
(let* ((qualifiers (butlast qualifiers-and-args))
(specialized-args (mapcar (lambda (arg) (typecase arg (list arg) (t (list arg t))))
(car (last qualifiers-and-args))))
(args (mapcar #'car specialized-args))
(specializers (mapcar #'cadr specialized-args)))
(alexandria:with-gensyms (method-obj method-fun next-args next-funs)
`(let* ((,method-obj (find-method #',name ',qualifiers ',specializers))
(,method-fun (closer-mop:method-function ,method-obj)))
(funcall ,method-fun (list ,@arg-values)
(list (lambda (,next-args ,next-funs)
(declare (ignore ,next-funs))
(destructuring-bind (,@args) ,next-args
,@next-function-body))))))))
(defgeneric foo (a b stream))
(defmethod foo :before ((a integer) (b string) (stream stream))
(format stream "~&~d ~a~%" a b))
(defmethod foo :after ((a integer) (b string) (stream stream))
(format stream "~&~d ~a~%" (1+ a) b))
(defmethod foo :around ((a integer) (b string) (stream stream))
(format stream "~&~d ~a~%" (+ 2 a) (concatenate 'string "b: " b))
(call-next-method)
(format stream "~&~d ~a~%" (+ 3 a) (concatenate 'string b " :b")))
(defmethod foo ((a integer) (b string) (stream stream))
(format stream "~&The primary method: ~s ~s~%" a b))
#|
CL-TESTING> (methodcall (foo ((a integer) (b string) (c stream))) (2 "foo" *standard-output*)
(format c "~&a : ~a b : ~a<<<<~%" a b))
The primary method: 2 "foo"
NIL
CL-TESTING> (methodcall (foo :around ((a integer) (b string) (c stream))) (2 "foo" *standard-output*)
(format c "~&a : ~a b : ~a<<<<~%" a b))
4 b: foo
a : 2 b : foo<<<<
5 foo :b
NIL
CL-TESTING> (methodcall (foo :before ((a integer) (b string) (c stream))) (2 "foo" *standard-output*)
(format c "~&a : ~a b : ~a<<<<~%" a b))
2 foo
NIL
CL-TESTING> (methodcall (foo :after ((a integer) (b string) (c stream))) (2 "foo" *standard-output*)
(format c "~&a : ~a b : ~a<<<<~%" a b))
3 foo
NIL
|#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment