On the contrary, nil punning seems exceptionally well suited to a dynamic language. In general, I'm only burned by nil propagating into Java, almost all Clojure code seems to handle nil appropriately.
I'm unsure of a good way to represent optionality in a dynamic language without a static type system. Or rather, doing so with the tools available -- core.match vs real pattern matching -- seems rather un-ergonomic.
I'm curious about your thoughts of what would be better.
You are right regarding the dynamic language, well, dynamic. I haven't put any thought into it and I can't come up with a viable solution of eliminating nil without some type system strategy (Maybe/Either Monads in Haskell, Option in Rust, etc). It's kind of a bummer, because I love the Lisp dialect of Clojure, but really appreciate software projects that I've written in the past that don't crash due to a forgotten potential nil value handling.
Yeah, I think many Clojurians would mildly agree some changes to how nil is handled would be nice... but this is such a fundamental behavior that it's very hard to justify modifying the language at this point for just a minor benefit.
I love the clojure community efforts, but clojure.spec is so confusing and bloat-y to me. :(
It reminds me of Frama-C and specification of C programs, which isn't exactly what I would want to do all the time to have some safety guarantees on my program. I feel that a strong type system would provide way more benefits.
Much as I love Clojure, I agree that clojure.spec, while very powerful, has a mess of a UX. That's why – shameless plug – I wrote Ghostwheel [1], which, to me, turns it into a whole other thing, especially when gen-testing, spec-instrumentation and tracing are used together.
Having inferred types in addition to this would be even better, but types are no replacement for generative testing or vice versa.
They really complement each other quite nicely, but also have a large overlap in terms of how much they can reduce the need to do manual debugging and enable clean changes/refactorings with minimal effort.
I'm unsure of a good way to represent optionality in a dynamic language without a static type system. Or rather, doing so with the tools available -- core.match vs real pattern matching -- seems rather un-ergonomic.
I'm curious about your thoughts of what would be better.