> 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".

I agree completely. But I'll note that you mention false being useful...

If you're writing completely general operators, like map, which are
*sometimes* quite useful, then you have no choice but to do something like
if-recv or explicitly test against nil.

> It's these Rx style programming methods that make people think they need
this feature.

I built my little Rx with channels library (asyncx) without intention to
use it directly, but because I wanted to learn how to work with channels. I
rapidly learned that the techniques are a lot more different than they
look. In particular, it's more difficult to write channel & process
combinators precisely because they are more powerful. However, in practice,
each new reusable channel/process combinator yields more complexity than it
tends to save. I'd rather intentionally choose strictly less powerful
primitives where appropriate and enforce that with encapsulation.

With that in mind, if I ever revisit asyncx, I'll probably define "push
sequences" or "streams" in terms of protocols and deftypes. I'd use
core.async to implement them, but only for the lowest level primitives. I'd
provide ways to get in to or out of the stream subsystem for interop with
channels, but the public interface would take IStream objects.


On Tue, Aug 27, 2013 at 10:58 AM, 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.

Reply via email to