clj-commons

qerub 2020-08-08T14:15:35.022500Z

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.

borkdude 2020-08-08T14:19:15.023300Z

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.

borkdude 2020-08-08T14:19:35.023700Z

They should maybe just catch Throwables instead of Exceptions

qerub 2020-08-08T14:20:56.024200Z

Nah, that will catch OutOfMemoryError and StackOverflowError too.

qerub 2020-08-08T14:21:43.025Z

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

borkdude 2020-08-08T14:21:54.025300Z

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

qerub 2020-08-08T14:22:45.025500Z

Agreed.

qerub 2020-08-08T14:24:04.026800Z

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

borkdude 2020-08-08T14:25:07.027200Z

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)

borkdude 2020-08-08T14:26:06.027900Z

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.

qerub 2020-08-08T19:54:57.028600Z

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

qerub 2020-08-08T19:55:15.029100Z

But there's assert of course.

borkdude 2020-08-08T19:57:42.029400Z

Ah, I must have confused it with Java

seancorfield 2020-08-08T20:23:25.034300Z

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.

👍 2
qerub 2020-08-08T20:29:17.035400Z

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

qerub 2020-08-08T20:30:10.036400Z

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

Alex Miller (Clojure team) 2020-08-08T20:30:20.036800Z

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

Alex Miller (Clojure team) 2020-08-08T20:31:07.037700Z

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

Alex Miller (Clojure team) 2020-08-08T20:31:46.038700Z

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

borkdude 2020-08-08T20:31:59.039Z

I think that makes a lot of sense.

Alex Miller (Clojure team) 2020-08-08T20:34:25.040100Z

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) 2020-08-08T20:34:58.040600Z

( nil) in particular gives me pause every time

Alex Miller (Clojure team) 2020-08-08T20:36:11.042Z

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) 2020-08-08T20:37:26.043Z

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