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
-~----------~----~----~----~------~----~------~--~---

Reply via email to