About realizing the head of lazy seqs in with-meta: On 5 November 2017 at 01:57, Didier <didi...@gmail.com> wrote:
> > That said, metadata and its relationship to an object is immutable - an >>> object with different metadata is a different object. One consequence of >>> this is that applying metadata to a lazy sequence will realize the head of >>> the sequence so that both objects can share the same sequence. >> >> On 5 November 2017 at 05:34, James Reeves <ja...@booleanknot.com> wrote: > On 5 November 2017 at 00:57, Didier <didi...@gmail.com> wrote: > >> And then I'm confused as to why that would cause lazy-seq to realize >> their head? Can't two lazy-seq share the same head? >> > > This I'm not too certain about. It may just be an implementation detail. > They can, and indeed the point of realizing the lazy seq in .withMeta / with-meta is precisely so that the input and output of with-meta share the same head. For example, in this situation: (def xs (create-some-lazy-seq …)) (def ys (with-meta xs {:foo 1})) the expectation is that the lazy seqs xs and ys will wrap a single underlying sequence. This is actually quite important – consider a lazy sequence that fully consumes some resource at each step or that causes some other side effect at each step, or perhaps simply one that is computationally expensive to realize; one would expect the above to work just fine in such a case regardless of how xs and ys are consumed, with any necessary computation, resource consumption, side effects etc. occurring once per element, and all the elements shared across xs and ys. In other words, if a consumer comes along and asks for the first element of xs, and then subsequently another consumer (or indeed the same one) asks for the first element of ys, the latter request should be satisfied without any further resource consumption or computation (beyond looking up a pointer). And similarly if ys is realized first and the second request is for an element of xs. Now, if xs' head has not been realized, (with-meta xs {:foo 1}) can conceivably operate in one of two ways: 1. it can copy over xs' thunk (the nullary function embedded in the lazy seq object xs that is called – and expected to return a sequence or nil – when xs needs to be realized) into a new lazy seq object ys; 2. it can realize the head of xs and call .withMeta on the result. The first approach, however, breaks the promise that realizing the head of xs will have the effect of realizing the head of ys, as neither xs nor ys would subsequently have any way of knowing whether the other's head has been realized when they finally need to realize their own heads, and so the second one to be realized would be forced to recompute the sequence. Thus the implementation takes the second approach. Cheers, Michał -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.