When I first started learning Clojure 3.5 years ago I was "bit" by this in my first month or so of doing Clojure but after spending a little bit of time to understand how the sequence abstraction works it was never a problem again. I agree with everything that Alex says here.
On Friday, September 9, 2016 at 10:04:44 AM UTC-7, Alex Miller wrote: > > > On Friday, September 9, 2016 at 11:36:22 AM UTC-5, Alan Thompson wrote: >> >> Hi Colin, >> >> I too have been bitten by this type of inconsistency in clojure.core >> functions. >> > > I disagree that the problem here is consistency. The core functions are > very consistent, but I think it's easy to build an insufficiently detailed > mental model of what should happen when you're not aware of the distinction > between collection functions (take and return data structures - things like > conj, merge, assoc, get) and sequence functions (take and return sequences > or really seq-ables - map, filter, etc). > > >> The root of the problem is that conj has different behavior for lists and >> vectors, and that a seq behaves like a list. When map, filter, etc convert >> the source vector into a seq, the behavior of conj changes accordingly. >> > > In my opinion, the root of the problem is not being aware enough of when > you move from working with data structures (like vectors) into working with > sequence abstractions. Becoming more aware of the distinction and when > those transitions occur is one of the more subtle aspects of learning > Clojure. > > I wrote this not too long ago on a very similar question on reddit: > > > https://www.reddit.com/r/Clojure/comments/4ve288/conj_i_just_dont_get_it_can_someone_help_me/ > > In order to avoid this kind of unpredictability, >> > > Just to belabor it, everything here is totally predictable already. > > >> you may wish to explore some of the functions to the Tupelo library. The >> goal is to make things simpler, more obvious & predictable, and as >> bulletproof as possible. One example is the append function. Here is a >> sample program comparing conj and append: >> >> (ns clj.core >> (:require [tupelo.core :as t] )) >> (t/refer-tupelo) >> >> (def v [1 2 3]) >> >> (conj v 4) => [1 2 3 4] >> (conj (map identity v) 4) => (4 1 2 3) >> (conj (remove (constantly false) v) 4) => (4 1 2 3) >> (conj (filter identity v) 4) => (4 1 2 3) >> >> > As I wrote in the link above, I don't ever write code like this. When > working with data in terms of seqs (map,remove,filter) you should be > thinking in aggregates not in terms of individual values. Calling conj > around a sequence is taking you from level of abstraction down into a lower > level. This never comes up when I write Clojure (not exaggerating for > effect, it just doesn't). > > I can't suggest an alternative here because the example is too narrow. > Occasionally (much less now that we have transducers) I will have data in a > seq and want to put it in a collection - into, vec, set are all sufficient > to do so. Usually I find that either I can just leave it as a seq and > continue OR that I can back up and make a collection instead of a seq in > the first place (by using transducers, into, etc). > > >> (t/append v 4) => [1 2 3 4] >> (t/append (map identity v) 4) => [1 2 3 4] >> (t/append (remove (constantly false) v) 4) => [1 2 3 4] >> (t/append (filter identity v) 4) => [1 2 3 4] >> >> >> > I disagree with everything about this. :) In my opinion you are working > against Clojure's strengths in going down this path. > > >> I think simpler and more bulletproof functions can go a long toward >> making Clojure easier to use, especially for beginners or when you are >> uncertain about the exact type of a parameter. >> > > I think more work on understanding the collection and sequence layers > would pay far greater dividends than what you are suggesting. > -- 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.