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

Reply via email to