Friday, October 7, 2016

warning: lisp geekiness

Nothing too special here, and I'm sure this will only be of interest to a few random geeky people, who knows where.  Maybe I should even put it on stackoverflow... but for now, I'm dumping it somewhere, so it doesn't get lost to time:

I was finding it a bit cumbersome to remove methods that I'd defined, which I wanted to remove because I wanted to change the argument count.  I wanted something simple (even better would be introspection and removing everything, but I couldn't find a portable way to do that -- if anyone knows of any, please let me know!), and was happy to do a bit of legwork to get something that would then be simple to use.  So, I came up with the following macro:

(defmacro easy-remove-method (name &rest args)
  `(let* ((modified-args (mapcar (lambda (x)
                                   (if (symbolp x)
                                       (find-class x)
                                       `(eql ,x)))
                                 ',args))
          (method (find-method ,name '() modified-args nil)))
     (if method
         (remove-method ,name method)
         (format t "Failed to find method (~a () ~a)" ,name modified-args))))

One could then call something like:

(easy-remove-method #'foo 1 'baz)

which would be equivalent to:

(remove-method #'foo (find-method #'foo '() '(eql 1) (find-class 'baz)))

Since I was working on methods which had integer-based eql specifiers, this made things much handier. In principal, I think you could just as easily place any other arbitrary object there and, as long as you didn't quote it and thus make it a symbol, you'd get an eql specifier for it. With the quote, you get find-class on that symbol. Which is just what I wanted, so yay.