I don't think you can confidently make the claim 3. Nothing in the spec (or
basic logic) says, that a send on a nil-channel gets ignored, does it? The
case-block never gets executed, yes, but that's a consequence of the
effects a) send on a nil-channel blocks for ever and b) select waits for a
communication that can proceed.

You might reasonably state that the *body* of a nil-channel case will be
ignored. I don't think it is at all a given that the whole case will be
ignored¹. To me, this difference seems to be the root of the discussion
here, conflating "the body can never be executed" and "the case gets
ignored".

You asked why this behavior was specified. I believe the reason was given:
It seemed like a natural choice at the point.

If you want a post-factum rationalization (I wasn't there) on why this is
the better behavior: How about "it is easier to specify"? Currently, the
spec doesn't mention nil-channels at all; the ability to use them to
disable a case is a natural consequence. Your change would require adding
that behavior, in that the right-hand-side of a communication is only
evaluated if the left-hand-side is not nil.

Also note, that switch statements aren't special in any regard here:
https://play.golang.org/p/OAlVMMY1Cw3
So to get your behavior you'd have to *also* change the behavior of a
regular send.

There is a third post-factum rationalization I can make up: If a send on a
nil-channel would not evaluate the right-hand side, I'd argue that it would
be surprising, that a send on a non-nil-channel would evaluate the
right-hand side *before the communication can proceed*. In fact, specifying
that the right-hand side is only evaluated once the communication can
proceed would probably be the most natural way to get the effect that you
request (and would be un-/surprising by the same logic). But that would be
weird to implement. Currently, you are evaluating the expression and push a
value to the queue. As soon as another goroutine pop's the value, you can
proceed. But if you can only evaluate the right-hand-side when the
communication can proceed, you need to instead push some sort of closure
that evaluates to the value. And given that this can take time, to prevent
races, you need to coordinate with the sender.
It's probably possible to do, but seems to have a bit of overhead and also
just seems somewhat awkward.

But in the end, I think Ian's comment is spot-on: You could spec a lot of
different ways, you have to choose one and this one doesn't seem
significantly worse than any other way.

[1] On the contrary, I would even argue that is a very weird assumption -
after all, you have to evaluate the expression in the case to know it's a
nil-channel.

On Tue, Jan 23, 2018 at 5:02 PM, dc0d <kaveh.shahbaz...@gmail.com> wrote:

> 1 - The case clause clearly represents a send action.
> 2 - So there must be a channel to send to, and f1() must return a channel.
> 3 - If that channel (returned by f1()) is nil, then the clause must get
> ignored.
> 4 - If the returned channel (returned by f1()) is not nil, then f2() will
> be executed.
> 5 - The returned value of f2() will be sent to channel returned by f1()
>
> Any unexpected side effects caused by either f1() or f2() are not relevant
> in the context of the above workflow.
>
> And since Go has not any specific semantics regarding side effects (like
> Haskell or Elixir), the problem of side effects has no place inside the
> context of Go semantics. Go is an imperative programming language, like
> many other mainstream programming languages.
>
> On Tuesday, January 23, 2018 at 7:21:24 PM UTC+3:30, Jan Mercl wrote:
>>
>> On Tue, Jan 23, 2018 at 4:45 PM dc0d <kaveh.sh...@gmail.com> wrote:
>>
>> > In the sample you have provided, a send syntax is used. And considering
>> that, (IMHO) f1() must be evaluated first.
>>
>> Consider f1() is a dispatcher. If it is to be evaluated first then it may
>> create and return a new channel that will not be used. Or consider if f1()
>> has a side effect of incrementing some send counter.
>>
>> I don't think asking a function to return a channel to send a value to,
>> while possibly later figuring out there's nothing available to send, is a
>> good idea.
>>
>>
>>
>> --
>>
>> -j
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to