> I don't see why the built-in concat couldn't be defined like yours. OK, great. I then ask that the core concat be changed to
(defn my-concat [& args] (when (seq args) (lazy-cat (first args) (my-concat (rest args))))) which has more or less the desired effect: user> (take 0 (apply my-concat (report-seq "" [[1] [2] [3] [4]]))) (first [1] ) (rest after [1] ) nil Actually, this is still slightly more eager than concat-elts: user> (take 0 (concat-elts (report-seq "" [[1] [2] [3] [4]]))) (first [1] ) nil which seems to be due to the definition of apply. Why does the rest get evaluated above? >>>> (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. Works for me, thanks. >>> (defn my-mevery? [f & seqs] >>> (every? identity (apply map f seqs))) >> > These could be changed to act like 'my-mevery?' above. Is this a > complete list? --> every? not-every? some not-any? Sounds perfect ... I think that's all of them. > 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 Perfect. >>> 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? Well, I've thought about this a bit more. I guess I'm a bit wary about your proposal, since as far as I know none of the existing core functions (except metay-things like ns, doc, ..) have their behavior changed by (especially, explicitly user- set) metadata. (Well, to be more precise, I don't know much of anything about how metadata is used by the core). Right now, I use metadata in a couple places in my code to store information about objects that I don't want to affect their equality semantics. If I could accidentally clobber metadata used internally by Clojure in doing so, that could be a bad thing. Is there a list somewhere of "reserved metadata keywords" that I shouldn't be using in this way? If not, after adding this it seems one would definitely be needed. On the other hand, part of me still likes safe-get, since the meaning is clear in the code: I will get the object associated with this key, or die trying. I may want to write a function that takes an arbitrary map and safe-gets some specific key, regardless of where the map came from. Or, I might like to sometimes "safe-get" and sometimes just "get" from the same map (i.e., if there are some required and some optional keys). Basically, it seems to me that most of the time, whether you want get or safe-get is a function of the *use* of the map and not the map itself. That being said, I guess there may be times when you really want the map itself to be safe (e.g., structs-maps?) or have a particular default value (come to think of it, I think I wanted this just yesterday). So maybe, both couldn't hurt? The names you give seem fine, or maybe (hash-map-no-default ...) or (hash-map-safe ...) and (hash-map-with-default def ...). >>>> (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. Hmmm, but sometimes I like to use nil/false values ... anyway, I'll agree that this utility has fairly narrow use cases and perhaps isn't worth putting in contrib. >> 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. > That would be perfect. -Jason --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---