On Feb 25, 12:19 pm, Konrad Hinsen <konrad.hin...@laposte.net> wrote:
> On Feb 25, 2009, at 17:40, David Nolen wrote:
>
> > Should print and println be multimethods? It seems the ability to
> > custom print a data structure would be generally useful.
>
> It's already there, just not documented as far as I know. All the
> printing routines end up calling clojure.core/print-method and
> clojure.core/print-dup, which are multimethods dispatching on class.
>
> > Not totally following here, looking at your code... Pardon my
> > slowness but why not dispatch on :tag first, and class if no :tag?
>
> That's possible, of course, but the result is a multimethod that
> works for (a) class-based types and (b) one specific type hierarchy
> hard-wired into the selector, such as your :tag. If I write some
> other type system, it won't fit in. That makes it impossible to
> define truly general interfaces that are open for anyone to implement.
>
> Take print-method in clojure.core as an example: How would you
> implement its selector, such that anyone could plug in their type
> system based on some tagging scheme? Perhaps one could come up with a
> scheme in which the selector function is itself a multimethod, but
> that would probably be quite messy.
>
> > Tags of course should be namespaced so is this really that much of
> > an issue in practice? Since tags are keywords they don't have the
> > interning conflict problem that symbols of the same name generally
> > do, right?
>
> Right. Namespaced tags go a long way to avoid name clashes. However,
> they are still not the private property of any one library module.
> Your namespaced tag is an object that can end up in any data
> structure, intentionally or by error. Only time will tell if this is
> a problem in practice.
>
> Anyway, my two main arguments in this issue are printing and open-to-
> anyone interfaces with multimethods. These are the problems that I
> had in my own code and that I wanted to solve. Printing is important
> for complex nested data structures and interactive use. Generic
> interfaces are a very nice feature to have. I came across this
> problem twice:
>
> 1) In clojure.contrib.accumulators. Ideally, it should be possible to
> implement additional accumulator types elsewhere, using the same
> interface. With the current implementation based on meta-data, that
> is possible, but only for data types that allow meta-data. It is thus
> not possible to build accumulators based on Java classes, at least
> not without wrapping them in a map or vector. Moreover, the selector
> function, based on meta-data with a fallback to classes, is neither
> elegant nor efficient, and much of the code in the library deals with
> the meta-data tagging scheme rather than with its real job.
>
> 2) In clojure.contrib.streams-utils. Again, I wanted to define a
> generic interface to data streams. At the moment, it uses a
> multimethod dispatching on class, but that doesn't leave much room to
> define different data stream sources. That was in fact what prompted
> me to write the types library.
>

You raise interesting issues and I'd like to explore them further. I'm
not sure the issues you have with type-tag-or-class dispatch are all
that prohibitive. In any case, I've added a type function that returns
the :type metadata or the class if none:

user=> (type #^{:type ::Fred} [1 2 3])
:user/Fred

user=> (type "foo")
java.lang.String

which should help people standardize.

If you want to multiplex multimethods for your ADT type, you can just
define a single :type ::ADT, and then sub-dispatch on e.g. :adt-type.

I'm not sure the mechanism you are using (actual Class types) allows
for any more overloading - Class is a single slot too, after all.
Interfaces offer some mixin potential, but they can't be superimposed
on existing classes. The same mixin capabilities of interfaces are
available for type tags, just say;

(derive ::my-type :freds/interface)
(derive ::my-type :ethels/interface)

etc.

The trick here is that you *can* superimpose such tags on existing
classes:

(derive String :freds/interface)

A bigger problem with the mechanism you've chosen is its dependence on
some implementation details. I haven't promised, e.g. that every fn
generates a unique class type.

Also, there may be issues on re-evaluation - it's not necessarily
going to yield the same classes.

Rich

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