Wednesday, May 23, 2007

Adventures in Factor metaprogramming

A few days ago, someone asked on #concatenative, the IRC channel pretty much devoted to Factor, how to remove a method from a generic word, I initially responded, "Why would you want to do that?" But this is Factor; we can do whatever we want. There shouldn't be anything too hard to do. This is not an insurmountable challenge, but it's not trivial either. At least I thought so.

I looked at how methods are defined to see how they could be undefined. I did this by recursively using the word see. First, I did \ M: see, then \ define-method see, and then \ with-methods see. What I found was that the method table is stored in the "methods" word-prop as some kind of assoc, class to method body, and each time a method is defined, the dispatch of the generic word is rebuilt. with-methods allows you to alter the methods assoc and then rebuilds the generic word. So removing a method should be a simple as adding one:

: remove-method ( class word -- )
[ delete-at ] with-methods ;

Unexpectedly, that was actually trivial, once I figured out how the core works.

After creating this brilliant, unique solution, Slava dropped in to the channel. He told us that, actually, Factor already had this functionality. You can do { class word } forget, which is implemented in pretty much the same way. So, the moral of the story is (a) Factor reflection capabilities are amazingly easy to use, and (b) the library already has tons of useful stuff, and you should know it well if you want to use Factor.

No comments: