On Feb 6, 5:18 pm, David Nolen <dnolen.li...@gmail.com> wrote:
> > I built 4 iterations of a model/protocol/thing system, accumulating
> > more requirements for it with each iteration. This discussion has had
> > the nice side-effect of grooming my requirements into a tidy state
> > that I can use for reference. What I'm doing next is stripping out all
> > of the m/p/t stuff and implementing the application in question
> > without any of it, to see which of the requirements are really
> > requirements.
>
> Yes, I myself have found it tricky coming up with something that doesn't go
> too far against the grain of the language.
>
> On the subject of Spinoza, when I read through the source, it reads
>
> > like a recapitulation of parts of tinyclos. tinyclos has the virtue of
> > presenting a reasonably complete metaobject protocol that can be used
> > to implement arbitrary OOP features. Maybe you don't want everything
> > in tinyclos, and maybe you don't want to do things in Spinoza the same
> > way that tinyclos does them, but if implementing a CLOS-like object
> > system, it still seems useful to compare the implementation to
> > tinyclos, if nothing else, to clarify the differences between what it
> > does and what is natural or convenient in Clojure.
>
> Thanks for the discussion and the reference.  I'll definitely check it out
> tinyclos.

For what it's worth, I am now working with an iteration of the m/p/t
code that includes an extremely simple implementation of models and
things. Protocols are specified in extensive detail, but not yet
implemented in the working version.

Serialization of protocols may be an issue. In the current code,
models, protocols, and things are all anonymous objects, and protocols
contain code for their methods. It's hard to see how to serialize and
deserialize protocols without turning it into a class loader issue,
since protocols contain functions. That's the main reason protocols
are not yet implemented; I'm giving it a few days while I think about
the requirements and ramifications.

As far as the present design of protocols, I think that works, apart
from the serialization issues. A protocol is a map from names to
protocol functions ("pfunctions"). A pfunction is in essence a
MultiFn, though they are not presently represented that way, for
reasons of implementation details. A pfunction is both a closure and a
map. It's a closure so that it can be applied to arguments (maps can
be applied, of course, but doing so does not do the right thing in
this case). It's a map from parameter specs to methods. Applying a
pfunction to arguments matches the supplied arguments against
parameter specs, selecting and applying a suitable method or, if none
is found, calling a default method (in the style of no-applicable-
method).

The matching process respects the model spec. An argument may match a
formal parameter spec any of the following ways:

x - matches any value

#^String x - matches any value of class String (or any subclass of
String)

#^{:model m} x - matches any value for which (model? x m) returns true

#^{:model [m1 m2 m3]} x - matches any value for which (model? x m1 m2
m3) returns true (the vector of models can of course be any length)

#^{:test f} x - matches any value for which (f x) returns true

The method lookup follows the rules of CLOS: check for a match on the
leftmost argument. If matches are found, check again on the next
argument to the right. When all checks are done, the leftmost match is
the most specific.

Class matches are more specific than "any value" matches; model
matches are more specific than class matches; multiple-model matches
are more specific than single-model matches; test matches are more
specific than model matches.

Models are simply maps. (model? x m) returns true if all keys of m are
found in x. (I may later introduce support for adding type or value
restrictions to keys). Yes, this means that matching involves sequence
comparison among models, and yes, that might be a performance issue.
If it's a burden, I'll add a mechanism for caching lookups.

Models know nothing about protocols or things; they're just maps.
Protocols know about models to the extent that they know how to do
parameter matching based on them, but know nothing about things. A
thing is a map made from some other maps (its models). Protocols whose
pfunctions match on those models will work on the thing.


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