Yes, Clojure.specs are technically not types, they cannot enforce constraints broadly at compile-time. Yet they still can enforce finer-grained constraints at runtime. From the practical point of view, specs are really great tool for building robust software and have other properties like simplifying property-based testing through automatic generation of test cases.
Take for example a trivial example when we need to validate user data with the following constraints:
- Age: Must be between 18 and 120.
- Name: Must be a non-empty string.
- Email: Must follow a valid email format.
- Credit Card Number: Must pass the Luhn algorithm check.
Something like that is pretty straightforward to achieve in Clojure.spec within 20 lines of code. It's close to impossible to get with any advanced static type system, because type systems can't deal well with custom constraints; they often can't offer detailed, human-readable error messages for the cases like that; they often can't describe complex and nested data structures, or trying to do so would be cumbersome and less expressive.
So, they are not types. Okay. Cisco built their cybersecurity platform using Clojure. The market capitalization is about $180B. I imagine this would be a few dozen billions more if they had chosen to use an "actual type system", amiright?
----
edit: After thinking about it a bit more, I have to admit that I spoke too harshly. It's not "close to impossible" You probably can create a type that checks for these constraints, but you would likely need to use a dependent type system or refined types, perhaps something like LiquidHaskell., and it still would be very tricky, especially with the credit card part. In Clojure.spec - it's very trivial.