Taking Chouser's suggestion of using a proxy that implements the IDeref interface, and overrides deref to provide access to a closed- over atom, I rewrote generic functions without resorting to gen-class or external Java files. That makes me happy; good suggestion, Chouser.
I made a couple of other improvements along the way. There is now an implementation of next-method that in theory should provide a way to call the next-least-specific method from the currently-executing method. This mechanism roughly corresponds with the idea of super in languages like Java and Smalltalk; it's not the same, because generic functions map a vector of argument matches to a method instead of mapping a single object type to a method, so next-method requires a scheme for sorting matching method signatures according to how closely they correspond to the actual parameters passed. CLOS does the same thing, but this implementation is a little more general than the standard CLOS dispatch (though you could use the meta facilities in CLOS to make a mechanism like this). CLOS matches actual arguments to formals according to class. It also supports eql specializers, which match actual arguments that are equal to a specified value. This implementation of generic functions for Clojure supports both of those kinds of matches, plus matching on a user- supplied test function. It also supports a simple means of customizing the dispatch: you can pass a vector of matching functions to make-generic-function, and it will use your matching functions instead of its default set. Each matching function takes two arguments, a value constraint and a value. The matching function should return false if there is no match, and a non-negative integer if there is a match. The integer can be used to order matches by specificity; smaller values mean greater specificity, with zero representing a perfect match. As an example, match-class?, which is one of the default matchers, returns these values: (match-class? java.lang.String 1) => false (match-class? java.lang.Object 1) => 2 (match-class? java.lang.Number 1) => 1 (match-class? java.lang.Integer 1) => 0 Thus, using match-class?, the first line is a non-match, and the lines following are increasingly-specific matches. A user who wants to create a custom dispatching regime can do so by calling make-generic-function thusly: (make-generic-function my-dispatch-sequence) ...where my-dispatch-sequence is a sequence of matchers in order of increasing specificity. The API currently includes: make-generic-function [& [dispatch-sequence]] define-generic [nm & [dispatch-sequence]] generic-function? [x] *standard-dispatch-sequence* match-wildcard? [fp ap] match-class? [fp ap] match-equals? [fp ap] match-test? [fp ap] add-method [gf params method-function] remove-method [gf params] method-table [gf] dispatch-sequence [gf] next-method applicable-methods no-applicable-method [args] remove-method shadows the standard Clojure function of the same name in the gf namespace. I removed match-model? from gf, because I think it more properly belongs in a separate file that implements extensions to model and gf to work with one another; that decision enables gf and model each to stand alone, not imposing both on anyone who might prefer to use only one of them. There are some efficiency improvements in the new implementation as well (for example,the old implementation had some redundant match tests in it because of the way it was structured). It still needs a lot of testing, and probably wants some refactoring before I let it out of my hands. This post is meant to provide interested parties the opportunity to grumble about obvious omissions or gaffes in the design and API while I'm preening the code for release. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---