On Apr 28, 7:17 pm, Douglas Philips <d...@mac.com> wrote:
> On 2010 Apr 28, at 6:55 PM, Stuart Halloway wrote:
>
> > Specializations are available where there is a clear use case, e.g.
> > contains?, peek (instead of last), disj, etc.
> ...
> > Tying to concrete types is limiting. *Never* having special purpose
> > fns that know about performance characteristics is also limiting.
>
> > contains?/seq-contains? mark a divide where it is very easy for a
> > language to quietly help programmers do the wrong thing.
>
> Such as littering my application code with type-checks to decide if it
> should call contains? or seq-contains?
> That seems exactly the wrong thing to do.
>
> Please explain how making seq-contains? fast for sets and maps is
> wrong (exactly how does it violate some contract and what contract,
> explicitly is that a violation of) and application code type checking
> is right, because I really don't understand why making seq-contains?
> fast isn't just a huge win-win.
>

It is an important aspect of Clojure that, in general, performance guarantees are part of the semantics of functions. In particular, functions are not supported on data structures where they are not performant.

You can't just swap out sequences or lists for maps or sets in a program. So, you need to use the right data structure for the job, and then the right functions will be available. When it makes sense, some functions are maximally polymorphic (e.g. seq, or into). But lookup, under any name, shouldn't be, IMO, so it isn't in Clojure. Similarly there is no insert at the beginning of vectors, append to end of lists, lookup for values of maps, insertion in the middle of sequences etc. I simply don't want to provide the tools for people to write programs in Clojure with N^2 performance - that benefits no one. But I've seen such performance degradation in many a Lisp program as people build upon O(n) functions on lists.

If you have a lookup table in your program, please use a set or map, or, if by index, a vector. You will have get, contains? or nth available, performance will be good, and that will be clear from the code.

seq-contains? exists because sometimes, say in a macro, you have a known short sequence and need to test for the presence of something. There's no need to copy it into a set. And people have been rolling their own includes? etc for this job. Now everyone can use seq- contains? for that. Its poor performance is indicated by its name and documentation. Should someone try to take a piece of code based on seq- contains? and try to scale it, they will see that function as an obvious bottleneck.

Your type-check argument is a straw man that doesn't hold up in Clojure practice. People tend to use the right data structures for the job and don't choose algorithms via type checks.

Clojure is not particularly duck-type-y, in general things are not unified by the presence of same-named functions but by underlying shared abstractions. Just because protocols can be used to make things reach many types doesn't mean they should be used to unify things that aren't uniform.

If you want to get a feel for how the abstractions in Clojure are organized, have a look at the slides in the middle of this presentation (about 30 pages in):

http://clojure.googlegroups.com/web/tutorial.pdf

While you may not agree with it (and everyone disagrees with contains? :), at least the design is a considered one.

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
Note that posts from new members are moderated - please be patient with your 
first post.
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