On Mar 25, 12:35 pm, Konrad Hinsen <konrad.hin...@laposte.net> wrote:
> On 25.03.2009, at 10:13, Mark Engelberg wrote:
>
> > 1. Structs don't inherently have a type.  If you want to dispatch on
> > type (a common use-case), you have to make a constructor that inserts
> > the type information as part of the struct.  Some have expressed
>
> And/or in the metadata.
>
> > concern that it may be too easy for this "type information" to be
> > altered, or worse, the data could be "changed" or "removed" in a way
> > that makes the struct inconsistent with the type label it carries
> > around.
>
> I am one of those who have expressed concerns, but I must also say  
> that until now I have not encountered such a problem in real life. I  
> have come to the conclusion that interfaces and types work  
> differently in Clojure than in other languages that most of us are  
> more familiar with. So perhaps we are expecting problems that really  
> aren't there once you figure out how to do it "right".
>
> > 2. No way to call "next-method" or "super", which limits the ability
> > to reuse related methods.
>
> Again, I'd like to see a real-life situation where this is an issue.
>
> > 3. The dispatch mechanism requires a lot of explicit prefer-methods,
> > or else it may be hard to guarantee you won't get a run-time error
> > from a situation the dispatch system considers ambiguous.  This also
>
> And there as well.
>
> > makes code less extensible because to add a method, you must know
> > about all the other methods that have been implemented in order to
> > insert all the appropriate preferences.
>
> This would only be an issue in complex hierarchies. As long as each  
> library just adds its types to a hierarchy and implements methods for  
> them, there is no problem. That's why I'd like to see the real-life  
> situation where there is one.

I repeatedly ran into all the problems Mark mentioned when trying to
write an extensible set of codecs for serializing and deserializing
game data, and for building a extensible set of data structures for
representing game state. The game in question is a relatively large
multiplayer RPG-style game whose data library needs to describe a
large number of different kinds of objects, support transfer of those
objects over networks and storage and retrieval on various kinds of
repositories, and which needs to be extended by a number of people on
an ongoing basis. I need to be able to clearly say what the protocols
are for creating existing objects, and for defining new kinds of
objects, and for serializing and deserializing them.

With a large number of types of objects, name collisions in field-
names becomes an issue. I can solve it by providing a mechanism to
define the names allowed in a particular kind of object, and a way to
declare requirements about the values allowed on those names. Storing
type tags in metadata is handy in that the type function then returns
the tag you want, and it's easy to make MultFns dispatch on those
values. On the other hand, not all objects that one might want to
dispatch on support metadata. That leaves storing type tags in the
object itself, which is fairly convenient, but as the disadvantages
Mark mentions. A partial workaround is to implement a feature for
decalring the fields allowed and required in maps, and to implement
consistency checking to ensure (to the extent that one can) that no
one uses the type-tag field for anything other than type-tags.

It's possible to provide a polymorphic API that covers each of the
various defined kinds of objects, but building that API involves a lot
of prefer-method calls. The inconvenience of that necessity increases,
seemingly without bound, as people add new kinds of objects and
methods to handle them. Each addition potentially requires its
implementor to examine an ever-increasing set of previously-defined
data descriptions and methods to determine what the correct prefer-
method calls are. There may not always be a correct set. When there
isn't, finding the data description and method definition that cause
the unsolvable problem isn't necessarily easy. I'm extremely
uncomfortable with any library that requires its user to be familiar
with all of its internals and all its dependencies; that's exactly
what libraries are meant to avoid. Therefore I am even more
uncomfortable with library-building tools that guarantee that's the
sort of library I'll be building.

The set of game data objects describes features of an imaginary world.
Those features (creatures, crafted items, factions, and so on)
naturally cluster into related taxonomies of shared and specialized
features. If you can say "this is just like those things except for
these features", you save a lot of duplicated code. Type extension is
one part of that ability; next-method is the other.

This is one "real-world" situation where all the issues Mark raised
are real and pressing issues for development, but it's not a special
situation. I've run into these issues many many times over the years.
They're why people keep on inventing mechanisms for type extension
over and over, and why they keep coming up with various different ways
to make protocols polymorphic. I ran into them almost twenty years
ago, working on a fairly large automated system for machine control,
written in a version of Common Lisp from before CLOS was widely
adopted. That project solved these issues by using a homegrown object
system.

If the language doesn't provide type extension and robust polymorphism
for protocols, its users will (assuming they keep using it).


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