Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

why is csp.CLOSED === null? #60

Open
jaawerth opened this issue May 12, 2015 · 6 comments
Open

why is csp.CLOSED === null? #60

jaawerth opened this issue May 12, 2015 · 6 comments

Comments

@jaawerth
Copy link

Hello!

I was wondering: why is csp.CLOSED currently equal to null? Wouldn't it make more sense to assign it an arbitrary object for reference equality (or possibly a Symbol in compatible environments) so "null" can be a usable value to send through a channel? I imagine this was your intention from the beginning (otherwise there'd be little point in giving CLOSED its own property assignment in the first place), just wondering if there's a reason it isn't already in place. I believe highland uses an empty object for the same purpose (_.nil) to allow streaming of null values.

@zeroware
Copy link
Contributor

You are right. The csp.CLOSED value has to be something else than null.

@jaawerth
Copy link
Author

Great, thanks for verifying I'm not crazy ;-). I'll submit a PR.

@tomvdsom
Copy link

tomvdsom commented Jun 3, 2015

csp.CLOSED === null is quite logical.

null is a sentinel for communicating you have no sensible value for something. The usual somethings are variables, marking empty places in data-structures and return-values.

Channels however are for communicating between some set of logical processes.

What intent can you possibly mean to communicate when communicating a sentinel who's soul purpose is to signify there is nothing to say?

Further, channels are not meant to be data-structures, nor are they forced to give a value (as function-calls do).

Ergo:

  • If there's nothing to say on a channel, say nothing.
  • Arbitrary data? Send it in a data-structure.
    Since channels communicate and synchronize; sending byte-sized chunks is also prohibitively expensive.

@summivox
Copy link

summivox commented Aug 8, 2015

What about using void 0 (a.k.a. undefined) instead?

null carries the connotation of "intentional absence of object" (see also chan struct{} in golang). This means it's completely reasonable to assign a special meaning to null value, regardless of in a channel, stream, array, etc.

void 0, on the other hand, has no such connotation. I'd say if we must express csp.CLOSED with an atom, then void 0 wins over null.

You can test for strict equality:

  • javascript: result === void 0 or result === undefined
  • coffee: result is undefined
  • livescript: result is void

@tomvdsom
Copy link

@summivox

Late reply

Sorry for the long delay - life kindof happened upon me, but anyway ...

  • void is simply an operator that always returns undefined - so we are actually talking about undefined.
  • golang channels are typed and return 2 things: <stuff_of_correct_type> and a true or false boolean value, indicating whether a channel is closed (see: A Tour of Go - Range and Close).

So using a single channel-result/response to represent a value or signaling closed is not something from golang; but a Clojure(Script) core.async way of doing things.

In core.async (Clojure: nil, ClojureScript: null) is used to signal a closed channel - and since js-csp mirrors most of core.async's ideas - keeping to use ECMAScripts null seems logical and ports over nicely from its Clojure cousin.

undefined o.t.o.h. does not exist in Clojure and is used instead of attribute-/method-not-found type of exceptions used in other languages.

Using a this-attribute-does-not-exist value as a return value to signal something that does not imply mostly that seems odd to me.

So if we want to keep a primitive value, I would keep it as-is: use null.

More pragmatic

Since there has been close to zero activity in this issue - and lots in of constructive talk around pull request #61, maybe the ship already sailed on this one and it is time to let go.

@loveencounterflow
Copy link

loveencounterflow commented Aug 25, 2017

FWIW pull-streams use null in a like manner to signal termination. It does seem like a bad choice when you think of streaming primitive values, but then in practice you often want to / need to stream more complex values (events) that carry some piece of metadata, like [ key, value, ] or { key, value, }. undefined is not necessarily better. Symbols are great but either you use private symbols which you then have to resolve via direct reference (which may be difficult for a distant consumer) or global symbols (Symbol.for) which don't have a uniqueness guarantee and thus might inadvertently overlap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants