--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Here's a somewhat old but still generally useful article on how Clojure vectors are implemented: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/
Vectors are optimized for random access, whereas lists are optimized for going through from the beginning to the end, which is exactly what the last function does.
--
For instance, one such function I wrote tonight is called every-other
(returns '(1 3 5) if you hand it (1 2 3 4 5))
The design choice has nothing to do with speed, it has nothing to do
with concrete types like lists and vectors either, no matter what
might have been said before by others.
David
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
As I said, if ISeq and ILast are both protocols that won't work. No
protocol inheritance.
--
ISeq *is* an interface on Clojure JVM. But ideally it would be
protocol as in ClojureScript. But then all ISeq implementing types
must also implement this new protocol you are suggesting to get these
basic *generic* sequence operations we enjoy today.
my understanding is that in Clojure, every protocol generates a Java interface, so I can't think of any reason why you couldn't list that generated interface as a "type" in another protocol (although I haven't tried it).
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
On Fri, Jun 29, 2012 at 4:50 PM, David Nolen <dnolen...@gmail.com> wrote:ISeq *is* an interface on Clojure JVM. But ideally it would be
protocol as in ClojureScript. But then all ISeq implementing types
must also implement this new protocol you are suggesting to get these
basic *generic* sequence operations we enjoy today.
I see, you're not saying it can't be done in Clojure, you're saying it wouldn't work on ClojureScript. It seems to me that's a limitation of either ClojureScript, or protocols, or both. My guess is that it's a limitation of ClojureScript, because my understanding is that in Clojure, every protocol generates a Java interface, so I can't think of any reason why you couldn't list that generated interface as a "type" in another protocol (although I haven't tried it).
Having separate "peek" and "last", with documented performance characteristics, makes it straightforward to reason about how code is likely to perform, a point that Mark made earlier.
It is a fundamental design principle of Clojure that, when given two approaches, A and B, make primitive the one that could be used to build the other. Clojure's "peek" and "last" might be useful to somebody building the "last" that Warren wants. Warren's "last" is *useless* for building the "peek" and "last" that Clojure already has.
Not arguing against having Warren's "last". Just saying that c.c/last ain't broken, and is simpler.
Stu
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Warren,I think the issue is this:You claim there is sg. broken in clojure while admitting that you know little about how the design decision was made.People that know clojure's implementation and the history of design decisions inside-out offered advice why they think it is not broken, they took time to explain the rationale for decision and even offerred advice how to "fix it" for yourself should you insist on your view of the matter.It seems to me youa) need to reread these arguments to perhaps get a better graspb) have chosen to ignore them.While you have right to do either of them, if it's b) not even the "clojure gods" can really help you unless you actually spend some time with the internals of clojure. ;-).Las
I think some people agree with me something is broken here (puzzler, for example. Please correct me is I am wrong as I don't want to hijack other people's opinion).
Wow, this thread was exhausting :) This reply is not to anyone in particular, just tagging on at the end (hint).
It is quite easy to come up to some part of Clojure, with some need, and some current perspective, and find it unsatisfying. It certainly is not perfect. But a good presumption is that there might be more context, more constraints, or more issues in play than one might recognize at first glance.
Mark was most correct in identifying that the algorithmic complexity dominates this decision. As far as the functions being defined in terms of abstractions: while true, the abstractions are still something that could be refactored. They are a means, not an end.
History: 'last' is a Lisp function. In Common Lisp it operates on lists only. It is a function that, there, advertises slowness by its mere presence. Code using it has a presumption it will only be used on short lists, and in fact it generally is; in macros and things that process code. People reading that code can presume the same.
I do think that, in general, it is bad to have a single polymorphic function that, depending on the target arguments, transitions between different algorithmic complexity categories (N.B. that is not equivalent to using polymorphism to get better performance by leveraging some implementation specifics, it is a specific subset). 'nth' for seqs is a counterexample, was requested by the community, and I still think is somewhat of a mistake. At least, it would be good to also have an 'elt' with specific non-linear complexity (for the reasons I give below).
Usually, there is a 'fast' function and someone wants it to work on something that would be in a slower category. This case is the opposite, 'last' is slow and people want it to be faster where possible. The end result is the same.
Why not just be as polymorphic as possible? In Common Lisp, there is a set of functions that lets you use lists as associative maps. The performance is not good as things get larger (i.e the sky falls). While this made sense at one point in time (when there were only lists), is it still a good idea now? Should we have functions that expect maps accept lists?
In my experience, having everything work on/with lists made it really easy to get a system together that worked on small data sets, only to have it crash and burn on larger ones. And then, making it perform well was extremely challenging. Some of that was because of the lack of interface-conforming implementations of e.g. hashmaps to swap in. but another category of problem was not being able to see what calls mattered for performance, when lists would still be ok etc. Thus Clojure 'forces' you to make some of these decisions earlier, and make them explicit. Even so, it is still highly polymorphic.
At the moment, I'm not sure it would be bad to have 'last' behave better for vectors et al while still promising in documentation to be not necessarily better than linear. But I do know this - it is seriously unimportant. We all have much better things to do, I hope, than argue over things like this.
There is a perfectly adequate and well documented way to get the last element of a vector quickly, and code for which that matters can (and should, *even if last were made faster*) use it. Code for which it doesn't matter can use 'last' on vectors because - ipso facto *it doesn't matter*! People reading either code will know what is and isn't important, and that seems to matter most.
Rich