This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (69)
- # aws-lambda (3)
- # babashka (45)
- # beginners (29)
- # calva (4)
- # clara (7)
- # clojure (23)
- # clojure-spec (5)
- # clojure-uk (18)
- # clojurescript (57)
- # clojutre (1)
- # cursive (20)
- # datomic (31)
- # emacs (5)
- # figwheel-main (3)
- # fulcro (16)
- # graalvm (7)
- # luminus (4)
- # nrepl (9)
- # off-topic (53)
- # re-frame (8)
- # reitit (2)
- # rewrite-clj (10)
- # shadow-cljs (88)
- # spacemacs (1)
- # sql (8)
- # vim (2)
@ericnormand I'm curious where you find spec to fall short in doing the static analysis of a type system?
Spec itself does zero static analysis. There is another add-on tool where another developer has implemented some amount of static checking on top of spec: https://github.com/arohner/spectrum
I'm sorry, that was a badly worded question on my part. I meant to ask if there is a class of errors where spec falls short compared to static analysis.
Back in the early '90s I worked for a company that built static analysis code tools (for C, C++, FORTRAN). There's a lot of stuff that static analysis can detect in a code base -- with a lot less effort than trying to find those problems with tests in general.
The tricky part is avoiding false positives -- you don't want to flag things that are actually correct just because they might violate some "rule" of the system.
And type systems are the same: there are a lot of correct programs that violate the type system.
When we were experimenting with
core.typed that was a problem we ran into at work.
It would complain about the type signatures of some of our code -- or be unable to deduce types from certain code.
Yeah kind of reminds me of problems with linters flagging something just because of a rule despite it making sense in the particular use case.
Wasn't sure of your mileage with it. I've used it at the boundaries of a couple apps to check input I don't have control over, and have been pretty happy with it.
We love Spec at work. Used it very heavily in production code since the early alphas. We use it for a lot of data validation (and conforming).
Totally agree. I'm just concerned with catching errors. I don't want to discredit a solution just because it's runtime and not compile time. I'm not sure how big of a role runtime vs compile time should play if the main concern is correctness.
Right, but if you use all these other techniques to ensure good code, how much benefit are you getting for the cost of a type system. Just exploring the cost benefit of a type system.
have you worked in a typed language? there's a lot of pros about them. and finding an expressive language makes it even better. its really nice when a helpful compiler works with you to ensure your code is typed correctly. there have been lots of studies but they're usually pretty superficial and not "real world". Best to try an expressive typed language and see if you dig it
Yeah, I've worked in C, Java, Go, TS, Rust, and Haskell. I still keep bouncing back and forth. I find that it helps me some times, but others it makes refactors, testing, and some simple things much more difficult.
(and i didn't mean to imply that you hadn't worked in typed languages, was curious. i find that preferring typing or dynamic is usually a pretty personal predilection more than anything else)
refactoring in C# with resharper was extremely powerful. And having a compiler direct is so confidence inspiring. I can't imagine changing the signature of some low level stuff in our current clojure codebase or in my last clojure job. ensuring the call sites were updated would be a nightmare
Sorry, I didn't mean anything by the list. It's just that all those take their own approach and I was hoping to find common ground. The refactoring bit, it definitely helps in some cases, but in others it requires more code changes over all. At first you have to modify the type, then possibly the interface, then possibly some references that don't care about your change, and only then you get to your logic.
that was never my experience. can you explain more what you mean by references that don't care about your change?
Well recently in Go, I had to move a concrete implementation to a interface to make a specific testing scenario work. Because of that I had to change a bunch references to now take an interface so I could pass in a mock of the interface.
All those changes were required only because there was a type system in the first place.
It's the reverse of the encapsulation argument: if you encapsulate data and use getters/setters then you can change the implementation as much as you want.
does go solve a problem for you that nothing else that you already know doesn't ?
Pros: It gives you a lot fewer opportunities to shoot yourself in the food. The code is straight forward to an extreme degree. You can teach it to someone in a day. A lot of decisions gets dictated by the language. Cons: The lack of abstraction gets frustrating quickly. The type system is limited. Error handling is tedious. A lot of decisions gets dictated by the language. I see why large enterprises started using it. It makes coordination between teams easy. But, I would not say I ever enjoyed using it.
i personally don't have problems to solve with Go ... for high level stuff i pick java or clojure for simplicity.... for low level i pick C or if i'm adventurous i go with Rust
things like append can either mutate or make a new thing at runtime which is super weird to me
If you Bing/Google for
go is an awful language or
what's wrong with go language you'll get a lot of detailed analysis that aligns with @U8QBZBHGD’s comment.
I share those opinions too. I was very disappointed with Go when I learned it several years ago. I learned Rust the next year and it was really what I had hoped Go would be in many ways.
if you seek a really good low level language then rust beats the pants off from go
the types discussion reminds me that I did use spec in my Building Composable Abstractions talk. https://lispcast.com/building-composable-abstractions/