On Wed, Jan 14, 2009 at 4:03 PM, Jason Wolfe <jawo...@berkeley.edu> wrote: > > To keep this manageable, I'll cut out the parts where I don't think > comments are needed.
Good idea! >> > (defn concat-elts "Lazily concatenate elements of a seq of seqs." [s] >> > (when (seq s) (lazy-cat (first s) (concat-elts (rest s))))) >> >> > (defn lazy-mapcat "Like mapcat but is lazy like map" [f s] >> > (concat-elts (map f s))) > > Yes. I would be happy to drop concat-elts and lazy-mapcat, if the > built-in concat (which seems to be used by mapcat) was changed to be > less eager (in the apply sense just mentioned above). > > user> (take 0 (apply concat (report-seq "" [[1] [2] [3] [4] [5]]))) > (first [1] ) > (rest after [1] ) > (first [2] ) > (rest after [2] ) > (first [3] ) > (rest after [3] ) > nil > > This can end up being a real drag in situations like (apply concat > (map #(recurive-call ...) ...)), since it may result in an exponential > amount of extra work being done. Any chance of this being changed? > (It should be possible to get rid of the last 4 evaluations here, > without getting into the territory of our last conversation about > laziness :)) I don't see why the built-in concat couldn't be defined like yours. >> > (defn chunk "Lazily break s into chunks of length n (or less, for the >> > final chunk)." >> > [n s] >> > (when (seq s) >> > (lazy-cons (take n s) >> > (chunk n (drop n s))))) >> >> This is so close to 'partition', that I think I'd prefer there be only >> one, or at least have related names. > > OK, I agree the name should be closer to partition (which I'd > forgotten about), but I think this one is at least as useful as > partition (You can recover partition from this one by (take-when #(= > (count %) n) (chunk n s))) but not vice-versa.) Any suggestions on a > name? Perhaps 'partition-all' ? I'd vote to have this in contrib. >> (defn my-mevery? [f & seqs] >> (every? identity (apply map f seqs))) > > Yes, I believe so ... that's a much nicer way of writing it. > >> Someone suggested all the functions that currently take a predicate >> and one seq ought to take multiple seqs and work like 'map'. I >> suppose this would include: every? any? some etc. Seems pretty >> convenient, and I've not heard arguments against it. But without >> that, I think I'd rather use 'identity' and 'apply map' than have an >> m-version of all the seq functions. > > Yes, I would of course prefer that the built-in versions take multiple > seqs and work like map. > If not, I guess I agree with you that it's better not to create m- > versions of everything. These could be changed to act like 'my-mevery?' above. Is this a complete list? --> every? not-every? some not-any? I believe functions that return the values from the input seq are NOT candidates for this? That includes: filter remove take-while drop-while split-with Instead the first three might suggest corollaries: map-when map-when-not map-while >> I think I'd rather this be a feature of the map itself, rather than >> depend on each 'get' to be a 'safe-get'. Perhaps if 'get' finds >> nothing and no default value is given, it could check the map's >> metadata for a :default-value or :throw-unless-found item. > > I think I'd be equally happy with "safe maps" as you suggest as using > safe-get. But, one or the other is definitely useful ... I've been > bitten several times by misspelled keys, which can create difficult-to- > find bugs. I know people have asked previously for maps that know their own default value. I suppose the metadata could be supplied directly: #^{:default "not found"} (hash-map :a 1, :b 2) That's a bit ugly, but you could use it on {} literals. Otherwise I guess you'd need extra constructors. (hash-map-default "not found" :a 1, :b 2) (sorted-map-throw :a 1, :b 2) (safe-array-map :a 1, :b 2) Hm. Is it worth it? Any naming ideas? >> > (defn merge-agree "Like merge but returns nil if there are >> > inconsistent key/value pairs." >> > ([] {}) >> > ([map] map) >> > ([m1 m2 & maps] >> > (when (every? (fn [[k v]] (= v (get m1 k v))) m2) >> > (apply merge-agree (merge m1 m2) maps)))) >> >> Maybe if it accepted the = function as a arg (like merge-with) it >> would be a little more general? > > Well, then which value would you use (if two values are my-equal but > not =)? Oh. Good point. I guess I was thinking it would be like 'merge-with', but if the conflict resolution function returned nil or false, you'd get back a nil instead of a map. > With merge-with, I think I would have to say > (apply merge-with + accounts (map (fn [[k v]] (hash-map k v)) (concat > deposits withdrawls))) > > which is considerably uglier and less clear IMO. Any chance of > changing merge-with in this way? Yes, it would just require replacing a use of 'key' and 'value' with 'first' and 'second' in the definition of 'merge-with'. I can't think of a good reason not to do this. --Chouser --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---