I still don't see why you would want to to arbitrarily limit what you can put down a channel. FWIW, plenty of other concurrency management primitives allow nils as values (java.util.concurrent.AtomicReference, Clojure atoms / refs / agents to name but a few).
My motivating use case is the ability to create higher order constructs that communicate via channels, as a way of gluing concurrent processes together. A simplified example: (defn printer [ch id] (go (while true (let [v (<! ch)] (prn (str "Printer " id " handled value: " v)))))) (defn sender [ch] (fn [xs] (go (doseq [x xs] (>! ch x))))) (let [ch (chan) pr1 (printer ch "1") pr2 (printer ch "2") sendr (sender ch)] (sendr ["foo" "a"]) (sendr ["bar"])) Using nil as a sentinel appears to prevent such constructs from working with arbitrary Clojure values (or alternatively forces extra wrapping / special case handling that adds complexity and overhead). Furthermore, if different libraries start adopting different protocols / techniques for wrapping nils then the composability of such constructs will be severely restricted. I may be missing something, but this seems like a reasonable use case for core.async to support? Of course, if anyone has an actual technical argument why it is necessary/better to use nil as a sentinel value, I would be delighted to learn of it and would consider myself enlightened. On 27 August 2013 22:58, Timothy Baldridge <tbaldri...@gmail.com> wrote: > All your arguments come down to this: > > "I have an arbitrary seq of things I want to send down a channel". It's > exactly that concept I that I push against. Everything you've mentioned > thus far is a data structure. Channels are not data structures they are > concurrency management primitives, treat them as such and I doubt you'll > ever have a need for nils in a channel. > > If we treat channels as ways of co-ordinating concurrent processes, then > nil doesn't have a use case. In every use of channels I've had thus far, > nil is better expressed as an empty collection, false, 0, :tick, or some > other "ground value". > > It's these Rx style programming methods that make people think they need > this feature. > > Timothy > > > > > On Tue, Aug 27, 2013 at 8:51 AM, Mike Anderson < > mike.r.anderson...@gmail.com> wrote: > >> On 27 August 2013 20:45, Timothy Baldridge <tbaldri...@gmail.com> wrote: >> >>> The reason for not allowing nils isn't a complex one, and basically >>> boils down to the following: >>> >>> a) to avoid race conditions, we need a single value to signal "the >>> channel is closed". As mentioned, nil is the obvious choice for this as it >>> matches lazy seqs and fits well with the rest of clojure: >>> >>> >> Agreed that you want a single sentinel value. >> >> It doesn't match lazy-seqs at all though: lazy seqs can contain nils just >> fine. There's a big difference between (next some-lazy-seq) [which could be >> nil, indicating an empty sequence] and the actual values in the seq [which >> could also be nil but don't indicate the end of the seq]. >> >> >>> (when-let [v (<! c)] >>> (process v)) >>> >>> If we chose a different value, this becomes much more ugly: >>> >>> (let [v (<! c)] >>> (when-not (= v :async/closed) >>> (process v))) >>> >>> >> This can be solved easily by providing a macro or some other predicate >> that knows how to check for the sentinel value correctly. e.g. >> >> (when-more [v (<! c)] >> (process v)) >> >> >>> b) I question if there are any valid uses for putting nil in a channel. >>> With all due respect to all who have written here, thus far, every >>> complaint about nils and channels boils down to a conversion from seqs to >>> channels. This is the wrong way to look at the problem. Channels are >>> co-ordination primitives not data structures. Simply because a lazy seq >>> looks like a channel, doesn't mean that they should be treated as such. >>> >>> >>> In all the core.async code I've written I've never had to put a nil in a >>> channel, so I'm left with the uncomfortable conclusion that most complaints >>> on this subject are contrived. I could be wrong, but I just haven't seen a >>> valid use case yet. >>> >>> >> To me it's all about consistency with other Clojure constructs. You can >> safely put nils in sequences, vectors, lists, sets etc.. nil is a valid >> "value" just like anything else. So why can't you put them in a channel? >> >> Two use cases I have encountered that motivate this: >> >> a) what if you want to send a sequence through a channel? Since nil as a >> value represents the empty sequence, you have to put in some extra special >> case handling with the current core.async model. >> >> b) what if you want to write generic code to send all the values in an >> arbitrary collection through a channel? you would have to wrap/unwrap nils >> at either end to make this work currently. >> >> Both of these, I think, are reasonable and common enough use cases that >> it's worth supporting them elegantly rather than forcing users to implement >> their own nil-wrapping functionality. >> >> >>> This all being said, there really isn't a technical reason to not allow >>> nils, it just simplifies much of the design and that probably translates to >>> better performance. So the restriction could be lifted if a rock solid >>> reason could be found, but as of yet, I haven't seen it. >>> >> >> I don't believe there is any noticeable performance difference between >> checking for nil and checking if a value is identical? to some sentinel >> value (which would presumably be static, final, immutable and hence very >> well optimised by the JVM). In addition, not allowing nils just means you >> have to do extra work to wrap/unwrap nils as a user - which is almost >> certainly a net loss on overall performance. >> >> Still, I think consistency is more significant than the performance >> argument in this case. >> >> >>> >>> Timothy Baldridge >>> >>> >>> On Tue, Aug 27, 2013 at 2:12 AM, Max Penet <m...@qbits.cc> wrote: >>> >>>> It's a real problem for me too, I also wonder what was the intention >>>> behind this. I guess there could be a very good reason for this special >>>> treatement of nils, but I haven't seen it yet. >>>> >>>> I would love to hear about this from people involved in core.async >>>> development. >>>> >>>> On Friday, August 16, 2013 4:44:48 AM UTC+2, Mikera wrote: >>>>> >>>>> Hi all, >>>>> >>>>> I'm experimenting with core.async. Most of it is exceptionally good, >>>>> but bit I'm finding it *very* inconvenient that nil can't be sent over >>>>> channels. In particular, you can't pipe arbitrary Clojure sequences >>>>> through >>>>> channels (since sequences can contain nils). >>>>> >>>>> I see this as a pretty big design flaw given the ubiquity of sequences >>>>> in Clojure code - it appears to imply that you can't easily compose >>>>> channels with generic sequence-handling code without some pretty ugly >>>>> special-case handling. >>>>> >>>>> Am I missing something? Is this a real problem for others too? >>>>> >>>>> If it is a design flaw, can it be fixed before the API gets locked >>>>> down? >>>>> >>>> -- >>>> -- >>>> 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/groups/opt_out. >>>> >>> >>> >>> >>> -- >>> “One of the main causes of the fall of the Roman Empire was that–lacking >>> zero–they had no way to indicate successful termination of their C >>> programs.” >>> (Robert Firth) >>> >>> -- >>> -- >>> 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 a topic in the >>> Google Groups "Clojure" group. >>> To unsubscribe from this topic, visit >>> https://groups.google.com/d/topic/clojure/pF9FEP7b77U/unsubscribe. >>> To unsubscribe from this group and all its topics, send an email to >>> clojure+unsubscr...@googlegroups.com. >>> >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >> >> -- >> -- >> 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/groups/opt_out. >> > > > > -- > “One of the main causes of the fall of the Roman Empire was that–lacking > zero–they had no way to indicate successful termination of their C > programs.” > (Robert Firth) > > -- > -- > 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 a topic in the > Google Groups "Clojure" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/clojure/pF9FEP7b77U/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > -- -- 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/groups/opt_out.