Fork me on GitHub
#clj-commons2020-08-08
>
qerub14:08:35

Anybody care to weigh in on https://github.com/clj-commons/camel-snake-kebab/issues/63 ? It's about how functions should handle an input of nil. I don't know what to think.

borkdude14:08:15

Personally I don't think nil should be returned. Exception is better. Compare with for example (name nil), I think no-one would want that to return nil.

borkdude14:08:35

They should maybe just catch Throwables instead of Exceptions

qerub14:08:56

Nah, that will catch OutOfMemoryError and StackOverflowError too.

qerub14:08:43

Those you usually (almost always?) want to propagate since something is really bad.

borkdude14:08:54

ok well, at least: > We had an issue in production where this happened w/ some unexpected input They should fix that problem on their end, making sure nil is never passed. How they deal with the error is up to them

qerub14:08:04

I'd still want to move from throwing an Error to an Exception since Error:s are unexpected for these kinds of problems (even though not really wrong).

borkdude14:08:07

It's pretty common to have assertion errors, e.g.:

user=> (defn foo [x] {:pre [(< x 5)]} x)
#'user/foo
user=> (foo 1)
1
user=> (foo 10)
Execution error (AssertionError) at user/foo (REPL:1).
Assert failed: (< x 5)

borkdude14:08:06

They can turn off assertions in their code if they want, using a System property. Then you'd probably get a NullPointer from somewhere else.

qerub19:08:57

There doesn't seem to be a system property for that (yet, https://clojure.atlassian.net/browse/CLJ-2554).

qerub19:08:15

But there's assert of course.

borkdude19:08:42

Ah, I must have confused it with Java

seancorfield20:08:25

FWIW, at one point I was grumbling that clojure.string functions threw exception on nil and it would be much nicer if they treated nil as an empty string or safely returned nil. So I tried it out with a forked version of clojure.string. First off, adding logic to handle nil slowed my programs down -- it turns out that even adding just one condition into every string function has a noticeable overhead in code that does a lot of string function calls (where they are nearly all non-`nil` arguments anyway). Second, it turns out that both alternatives tend to cause (or allow for) more subtle errors that are harder to track down because, instead of blowing up early as it does now, silently returning nil or silently treating nil as "" just allows for an unexpected value to crop up further down the line in the code execution. I was a bit surprised by that, but it was more convincing than the (noticeable) performance overhead and that changed my position: string functions should not accept nil: they should just blow up.

qerub20:08:17

I think your concluding statement could be generalized to all/most functions from "string functions"…

qerub20:08:10

Have we got any examples of when silent/"safe" handling of nil is actually a good thing?

Alex Miller (Clojure team)20:08:20

just fyi, the rationale for clojure.string is explained at (doc clojure.string)

Alex Miller (Clojure team)20:08:07

when doing Java interop, the nils do what they do in Java - NPE

Alex Miller (Clojure team)20:08:46

when doing Clojure collection or sequence operations, those functions typically are polymorphic on nil and do something useful

borkdude20:08:59

I think that makes a lot of sense.

Alex Miller (Clojure team)20:08:25

clojure.string is explicitly acting as a set of interop calls. http://clojure.java.io does not though, and honestly this has thrown me off a few times

Alex Miller (Clojure team)20:08:58

( nil) in particular gives me pause every time

Alex Miller (Clojure team)20:08:11

I've come to appreciate that returning nil though as you can avoid checking for a nil arg and just check the resulting file instead, which is usually better (but also trouble in stuff like (.exists (file nil)) )

Alex Miller (Clojure team)20:08:26

file is a pretty clear that it's a polymorphic protocol backed thing though so it is pretty clojurey