If I should happen to find a fix for any problem I might run into, or come up with ideas for improvements, I'll be happy to contribute.
However, if you're really scared, you can do
(declaim (optimize (speed 0) (safety 3)))
and really precise run-time type assertions will be inserted into the code.1. Learned to program in dynamic languages;
2. Learned FP in Clojure;
3. Writes [mostly, wherever possible] FP code in TypeScript for the last several years…
… I wish Clojure.spec was this or something a lot like it instead.
It’s cool that Clojure tried a novel approach to defining interface boundaries in a dynamic language. Other approaches (TS, Python, even PHP) have prioritized static analysis first with varying approaches to runtime. I think Clojure missed a design opportunity here by inverting that.
A design which treated spec as annotation first, runtime optional would have been an excellent opportunity for something like Coalton (or mypy) as a third party offering.
Ultimately this is mostly a cultural divide (as noted everywhere). But it’s a gap that’s hard to bridge without a huge effort like this. TypeScript is probably the most successful (reach) externally maintained type system for a dynamic language, but only on account of JavaScript’s own success in reach and being owned and invested in by a megacorporation. Doing this with Clojure (or any lisp) is infeasible without similar metrics.
I’ve often thought “there’s enough flexibility with Clojure, start it as a hobby project and see where it goes”. But I’m deterred because:
1. Even hobby projects using tech in ways it’s not designed for is a huge slog (me says as I go into weekend umpteen staring at a yak shaving integration with esbuild/Node/test runner).
2. The bar is very high. If you don’t support LSP, you’re basically barking at the moon. If it’s not syntax highlighted in README.md, no one’s interested. If it’s not mature there’s not enough adoption to build a community around it to even get it syntax highlighted. If it’s static typing in a lisp, you’re already narrowing the audience that might disregard all of the rest.
Sorry for the novel when you didn’t even ask me, but… this is all pretty much what flooded my thoughts the moment I saw/read this post and asked myself “how do I feel about this relative to clojure.spec?”
I think if I were looking at an ML language I’d be more inclined toward F#.
Many technologies have tested this dichotomy; even very mainstream languages, like Python with type annotations and mypy. However, what I've found consistently lacking is the "completeness" of either side of the experience: either half-baked dynamicism buried in a static language, or type annotations that actually don't have predictable correctness guarantees—typically, type checkers in this arena are "best effort".
Coalton doesn't try to paper over Lisp as a dynamic language, or try to change the philosophy of Common Lisp code by restricting it, but instead invites static features as a separate, well-defined language within Lisp. Critically, though, inter-operation between Lisp and this separate language must be essentially free.
Coalton makes use of what many cite as Lisp's greatest power: the ability to do seamless metaprogramming and syntactic abstraction. Often, non-Lisp programmers, especially in forums like these, see these features get used for programming party tricks. (I myself have even engaged in such shenanigans, like saying macros are good for making DSLs like
even though the next natural question would be, "Why would I ever actually use that?") In that regard, Coalton is implemented actually as quite sophisticated Lisp macros, without any separate (pre-)processors.Though it has some sharp edges as an alpha release, we think Coalton satisfies the objective of bridging static and dynamic, and opens a very interesting and relatively under-explored paradigm of functional programming.
Coalton isn't the first to explore this space in earnest. In fact, Racket, Typed Racket, and Hackett have done so quite successfully. There are several others, as well.
Lastly—though I think it goes without saying—there's value in having an entire language buy in to some core ideas, because it means library authors and application developers can have solid expectations of one another. As a Lisp developer, though, I've witnessed that a clean, modular coding style allows many programming styles to participate with one another without the headache one might imagine.