ClojureScript

(inc nil) returns 1 instead of throwing an exception

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Declined
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:

Description

(inc nil) => 1 in ClojureScript
(inc nil) => raise NullPointerException in Clojure

I think that Clojure's behavior (throwing) makes more sense in this context.

Activity

Hide
David Nolen added a comment -

tickets of this nature aren't going anywhere without a fairly serious design pass on CLJS numerics.

Show
David Nolen added a comment - tickets of this nature aren't going anywhere without a fairly serious design pass on CLJS numerics.
Hide
Fogus added a comment -

David,
That was ultimately the solution, so I suppose we need to start advocating this pattern so that others might avoid the same fate.

Show
Fogus added a comment - David, That was ultimately the solution, so I suppose we need to start advocating this pattern so that others might avoid the same fate.
Hide
Evan Mezeske added a comment -

@David Nolen: Yeah, fnil would do the job. In my case, I was calling update-in on what I thought was an initialized map, but it was actually nil. update-in initialized each level of nesting with an empty map, and then inc was called on nil. My fix was simply to initialize the nested maps like I meant to.

Show
Evan Mezeske added a comment - @David Nolen: Yeah, fnil would do the job. In my case, I was calling update-in on what I thought was an initialized map, but it was actually nil. update-in initialized each level of nesting with an empty map, and then inc was called on nil. My fix was simply to initialize the nested maps like I meant to.
Hide
David Nolen added a comment -

It doesn't seem to me that you could do that safely without fnil + 0. I too hate JS's silent failures around numerics. Been hoping someone would tackle this challenge with gusto.

Show
David Nolen added a comment - It doesn't seem to me that you could do that safely without fnil + 0. I too hate JS's silent failures around numerics. Been hoping someone would tackle this challenge with gusto.
Hide
Evan Mezeske added a comment -

@Fogus: Huh, that is the exact same use-case that burned me – I was using update-in/inc on a nested map. The default value for my [:foo :bar] was, in fact, supposed to be zero, so it silently worked for me. But when I moved that code from the client in my webapp (ClojureScript) to the server (Clojure), I found out that my original implementation was wonky.

Show
Evan Mezeske added a comment - @Fogus: Huh, that is the exact same use-case that burned me – I was using update-in/inc on a nested map. The default value for my [:foo :bar] was, in fact, supposed to be zero, so it silently worked for me. But when I moved that code from the client in my webapp (ClojureScript) to the server (Clojure), I found out that my original implementation was wonky.
Hide
Fogus added a comment - - edited

One place that this has burned me, that may warrant a separate card is

(update-in some-map [:foo :bar] inc)
where the key at that location did not exist. I would have preferred an exception rather than an broken 1.

Show
Fogus added a comment - - edited One place that this has burned me, that may warrant a separate card is
(update-in some-map [:foo :bar] inc)
where the key at that location did not exist. I would have preferred an exception rather than an broken 1.
Hide
Evan Mezeske added a comment -

Fair enough! I thought Won't Fix had stronger implications than that. Do you know if there's already a design doc that addresses numerics? Or should I start one?

Show
Evan Mezeske added a comment - Fair enough! I thought Won't Fix had stronger implications than that. Do you know if there's already a design doc that addresses numerics? Or should I start one?
Hide
David Nolen added a comment - - edited

Closing as Won't Fix doesn't mean we don't care, but this issue is simply a symptom of something much larger - punting on numerics. A ticket is the wrong place for this discussion as it has many nuances. It should be a part of a larger design for ClojureScript numerics. Without that larger discussion this ticket is likely to get stuck in limbo.

Show
David Nolen added a comment - - edited Closing as Won't Fix doesn't mean we don't care, but this issue is simply a symptom of something much larger - punting on numerics. A ticket is the wrong place for this discussion as it has many nuances. It should be a part of a larger design for ClojureScript numerics. Without that larger discussion this ticket is likely to get stuck in limbo.
Hide
Evan Mezeske added a comment -

I do not. I haven't had a chance to put a lot of thought into it, though.

I consider this kind of problem to be rather insidious. Null is not a number, and treating it as zero will lead to nasty bugs creeping into people's code.

A historical anecdote: the C function "int atoi(char* s)" takes a string and returns the number it represents. However, if the string can't be converted, it returns zero (which could also be a valid result for e.g. the string "0"). Technically, it's possible to distinguish "0 meaning error" and "0 meaning 0" by taking additional steps after the function call, but in practice people forget to do this. Thus, atoi is universally a disaster. I have literally seen the lights go off in a warehouse due to atoi's poor design (I used to work in building control).

Treating null as zero will result in similar problems. Someone forgets to check the result of a computation, it's null, and the program silently continues as if nothing is wrong. Hello, data corruption.

So I seriously urge you to not close this as Won't Fix, even if a performant solution is not yet obvious. IMHO it's worth more thought.

Show
Evan Mezeske added a comment - I do not. I haven't had a chance to put a lot of thought into it, though. I consider this kind of problem to be rather insidious. Null is not a number, and treating it as zero will lead to nasty bugs creeping into people's code. A historical anecdote: the C function "int atoi(char* s)" takes a string and returns the number it represents. However, if the string can't be converted, it returns zero (which could also be a valid result for e.g. the string "0"). Technically, it's possible to distinguish "0 meaning error" and "0 meaning 0" by taking additional steps after the function call, but in practice people forget to do this. Thus, atoi is universally a disaster. I have literally seen the lights go off in a warehouse due to atoi's poor design (I used to work in building control). Treating null as zero will result in similar problems. Someone forgets to check the result of a computation, it's null, and the program silently continues as if nothing is wrong. Hello, data corruption. So I seriously urge you to not close this as Won't Fix, even if a performant solution is not yet obvious. IMHO it's worth more thought.
Hide
David Nolen added a comment -

Do you have any suggestions on how to make this work without slowing arithmetic down? If not I'm inclined to close this as Won't Fix.

Show
David Nolen added a comment - Do you have any suggestions on how to make this work without slowing arithmetic down? If not I'm inclined to close this as Won't Fix.
Hide
Evan Mezeske added a comment -

I observe that in my JS console, "undefined + 1 => NaN" but "null + 1 => 1". I assume this has something to do with this issue.

Show
Evan Mezeske added a comment - I observe that in my JS console, "undefined + 1 => NaN" but "null + 1 => 1". I assume this has something to do with this issue.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: