On Mon, Dec 6, 2010 at 4:44 PM, Mike Meyer <mwm-keyword-googlegroups.620...@mired.org> wrote: > On Mon, 6 Dec 2010 16:30:10 -0500 > Ken Wesson <kwess...@gmail.com> wrote: > >> On Mon, Dec 6, 2010 at 1:05 PM, Stuart Sierra >> <the.stuart.sie...@gmail.com> wrote: >> > On Dec 6, 8:36 am, Ken Wesson <kwess...@gmail.com> wrote: >> >> Furthermore, the comment (not made by Hickey) that map order "may be >> >> unstable" is more than a little puzzling in light of the fact that the >> >> maps in question are immutable. :) >> > >> > In general, Rich has been careful not to promise things that might >> > limit changes he can make in the future. Sets and maps are unordered. >> > `seq` happens to be deterministic on ArrayMap and HashMap, but there >> > might some day be some other kind of map or set for which `seq` cannot >> > be deterministic. Therefore, Clojure does not promise anything about >> > `seq` on maps, other than that it will return the key-value pairs. >> >> I confess I can't see any obvious reason ever to make seq >> nondeterministic on an immutable data structure. > > I suspect you're applying "immutable" to everything about the data > structure, whereas it can also be applied the value without including > the implementation. I can see wanting to change the implementation in > ways that don't change the value - triggered by something like wanting > to share parts of the value with another structure, or a garbage > collection, or ... - which could easily change the results of calling > seq on the structure.
Perhaps. But under those circumstances seq itself has the same problem you're using to excuse not supporting nth, yet seq is supported. And so is (nth (seq x)) on these things; if the implementation changed its innards while you were walking the seq (even with map! Nevermind using nth) this could trip up. You might have a set #{1 2 3 4 5 6} and seq would produce (1 3 4 5 2 6) and then someone makes another set from it with disj and the structure rearranges, so seq would now produce (1 5 6 2 4 3). Meanwhile, another thread has produced a seq and is traversing it at the time and gets (1 3 4 2 4 3). Oops. If that kind of internal rearrangement is to be done, seq will have to copy the structure's contents (by realizing the seq promptly; so there goes laziness) in order to avoid that kind of error. And once you have that, you will want to create AND CACHE the (immutable!) structure's seq-representation when it's first needed. And you can do so when nth is called, as well as seq. And then due to the caching both nth and seq will obey (if (identical? s1 s2) (identical? (f s1) (f s2))) when substituted for f. Even then, I'd expect internal rearrangement to be a thread-safety nightmare; in all likelihood a) rearranging operations, and b) operations like realizing the seq that will be b0rked by concurrent rearrangements, will require locking the structure. Locking is supposed to be kept to a minimum as one of Clojure's design goals, IIRC. This gets worse when you note that seq realization can cause the execution of user-supplied code (e.g. the body of a lazy-seq macro) during realization. If user-supplied code can end up executing with user-invisible monitors locked, and can in turn cause more monitors to be locked (say, by disjing a set thus causing one of your hypothetical internal rearrangements), then it can cause deadlocks that would be fiendishly difficult to track down and fix. And deadlock avoidance is *emphatically* one of Clojure's design goals. -- 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