4 ms·
Because you want the type safety of lisp with the simplicity of the jvm /s
by moi2388 2y ago
Because you want the type safety of lisp with the simplicity of the jvm /s
- gleenn 2y agoYou are being snarky but I'll take immutability over types and interoperability and access to a vast and stable ecosystem over the simple and extremely limited and underperforming alternatives. Thanks for the segway. I also cannot understate the reasoning ease that comes with basically everything being a static, top-level function. Testing never requires mocks because you can redef any function anywhere trivially when you otherwise would reach for a mock which tends to be painful, complicated, and requires comlex mocking libraries. Even with immutability by default, you get an extremely performant platform that usually stomps on nearly all the dynamic languages you might otherwise choose like Python or Ruby etc. And you get first-class functions and a concise and extremely stable language that is a joy to program in. Thanks Rich and Alex!
- AnimalMuppet 2y ago> I'll take immutability over types and interoperability OK. > Thanks for the segway. A segway is a motorized transport; a segue is a transition to a different topic. So this could be considered a type error, and demonstrates why you need types, not just immutability.
- slowmovintarget 2y agoWhile amusing, I still disagree. Complex static type syntax ends up infecting your code, because the syntax becomes load-bearing. A change to one type has a tendency to ripple through the entire body of code. This means you have tight coupling as a consequence of the syntax, which is a bad trade-off. Clojure's strong dynamic abstract types allow you to focus on the function of the code instead of its structure. Trying things out in the REPL first helps you find many of the things that you might need to wait for a compiler to find. There are studies that estimate that the kind of bugs shipped to production that strong static types help prevent account for only 2% of defects. The rest are things like off-by-one errors, design errors, and incorrect logic. The other thing a static type system can help you with is reading code. But it's primarily an aid to people unfamiliar with the language, or put in more popular parlance a "skills issue." We know tooling can navigate the code, because we have tooling that does so (language servers, CIDER, Calva, Cursive, Conjure...). This means that static typing for the purpose of merely reading the code is a crutch. I'd argue it's also a crutch or training wheels for writing correct code. You can't run with crutches. You can't corner well with training wheels. Clojure is meant to make the expert nimble and fast. The main thrust of its design is to make experienced devs more productive, like professional tools without novice guide-rails make experienced craftsman more productive. Rich Hickey gave a talk where he mentioned this idea of guardrails on the highway. He told a story of how we all get in our car, then bump into guardrails all the way to our destination... right? Of course not, we learn to keep the car in our lane of travel, to signal others when we switch, and to blend with other traffic on the way. (Rich was talking about TDD, but it still applies to static type systems, IMHO.) Clojure is that power tool without all the novice presets. It's the automobile we keep away from the rails when we drive it. Mutable state is arguably responsible for far more defects shipped than type errors. Mutability is only a thing because hardware constraints required reuse of memory locations instead of allowing for persistent data structures. Thankfully, for "situated" applications that start and operate for extended periods, those constraints aren't so tight. If you have to choose between immutable data and static types choose immutable data. But why not both? We can have all our luxuries, right? Because you have to spend so much more time proving things to the compiler, you have so much more syntax to manage. More code and more syntax for the same problem is almost always worse. I'll take Clojure.
- AnimalMuppet 2y ago> There are studies that estimate that the kind of bugs shipped to production that strong static types help prevent account for only 2% of defects. The rest are things like off-by-one errors, design errors, and incorrect logic. If you've got a reference, I'd be interested. (Not saying you're wrong...) > The other thing a static type system can help you with is reading code. But it's primarily an aid to people unfamiliar with the language, or put in more popular parlance a "skills issue." It's an aid to people who are unfamiliar with the program, who have no idea what the shape of "that thing" is. (Especially, what is the shape of the thing that this function gets called with? For all possible callers?) I've been hired to start working on code bases that have existed for a decade or two. Static, stated types are a life saver. Sure, they may slow you down while you're creating the code. It's easier to not have to explain everything that's in your brain. But when you and your brain leave, and I'm left with a bunch of variables that I have no idea what type they are - what are the maximum set of types that they can be for all paths through all callers - then I really need static types to help me figure out what's going on.
- slowmovintarget 2y agoOr you need a REPL that lets you poke at the living code. It's just different.
- Capricorn2481 2y agoI think their point is, even with the REPL, it takes time to track down every spot that function might be called and figure out what was passed to it. A type is very easy to see localized on the function.
- iLemming 2y ago> A type is very easy to see localized on the function. "You Keep Using That Word, I Do Not Think It Means What You Think It Means"... When you say "types," can you please give a concrete example of what languages you're talking about? Whenever someone talks about Clojure from type theory talking points, they make it sound like it's completely untyped or weakly typed. Clojure has its own type systems, and you can express things in them that are far more difficult to do in some other languages, even with static types. It is also a strongly typed language, and in practice, I feel far more confident about our Clojure code than anything written in TS or Java. Sure, static type systems have their value, and some of them are really nice. In practice though, whenever I have to jump in to deal with Java, Typescript, or even Rust code - there's so much seemingly unnecessary fluff, and I don't feel the practical worth of dealing with types - it almost always feels taxing. Haskell/OCaml is a different story - I can buy that one. But realistically, getting to the point of writing practical software in Haskell is an incredibly bumpy road, and (relatively) few programmers successfully achieve good milestones on it.
- synthc 2y agoImmutability removes so much accidental complexity, it makes whole classes of mistakes dissapear. I'd also take immutability over types. Clojure sort of guides you to simplicity, building everything out of functions and simple datastructures has big advantages when testing and reasoning about code. I do find that in larger code bases, Clojure lack of types causes friction (spec is just a bandaid, not a fix). There are languages with immutability and types (like Haskell), but these don't have the get-shit-done factor I seek.
- yogthos 2y agoI've used Clojure for over a decade and the JVM has never been an issue. The only people I see complaining about the JVM are people who never actually worked with it. Meanwhile, there's zero evidence for the notion that static typing has any impact on code quality. https://danluu.com/empirical-pl/ https://danluu.com/empirical-pl/
- huahaiy 2y agoFor someone who needs static typing, Clojure give them defprotocol, deftype and defrecord. Interestingly, most of the low level libraries in the Clojure ecosystem are programmed that way. If you open up the code of many popular Clojure libraries, you see defprotocol everywhere. So really, Clojure does both: dynamic typing for application programming, mostly static typing for infrastructure library code. As they should be. This tired argument of "Clojure bad for dynamic typing" just doesn't hold water. Keep repeating it is a sign of lack of critical thinking.
- yogthos 2y agoI'd argue defprotocol, deftype, and defrecord provide much weaker guarantees than a type system. Dtuff like defprotocol tends to serve a similar use case to using an interface in Java. You specify the signatures for the functions, and then a concrete implementation can be provided using a library. Ring servers are a good example of this where you can easily plug different server implementations by just swapping a library. There is Typed Clojure https://typedclojure.org/ https://typedclojure.org/ for people who want actual static typing, but the fact that it never caught on suggests this wasn't a real pain point for most people using Clojure. As other people mentioned, immutability tend to be a more important feature than static types because it makes it easy to write code that's referentially transparent. You can structure your whole application as a series of small components that can be reasoned about in isolation.
- huahaiy 2y agoNobody would argue that Java is not statically typed. That's my point. Clojure offers the same as what Java offers. If you write code in a defprotocol everywhere style, as many Clojure libraries do, your code won't compile if you got the types wrong. The same as Java. How's that not static typing? Which part of that is weaker? So what exactly this "Clojure dynamic typing" nonsense is about, I fail to see. Automatically inferred type system is not the same thing as static typing. Typed Clojure is the former. Typed Clojure did not catch on, but static typing style of Clojure did, as many Clojure libraries do exactly that: internally, defprotocal everywhere, externally, some Clojure functions to give the illusion of normal Clojure code. BTW, that's the style how Clojure itself is written in as well.
- iLemming 2y agoClojure is strongly typed. That manifests in, for example, when Clojurescript emits compiled Javascript. Surprisingly, often it emits safer Javascript than Typescript ever could with all its static types. Typescript's type system exists only at compile time for development and static analysis. When compiled to Javascript, all type annotations and interfaces are removed, leaving code that runs dynamically at runtime, meanwhile Clojure retains its strongly typed guarantees. Coders often accept the status-quo of things - "So what that we can't easily upgrade our dependencies in our Node/Ruby/Python project - it's a known thing, we just have to deal with it..."; "Of course our builds take 90 minutes, that's normal for a big project"; "We need complex state management like Redux"; "Code must be recompiled after every change"; "Testing requires mocking everything", "Type safety prevents runtime bugs"; etc. Yet, when it comes to actual work, not some cheap talking points but real, practical scenarios - there aren't many other tools that can beat Clojure for robustness, pragmatism, and speed of building things with it. Most experienced Clojuristas are incredibly knowledgeable, skilled, and seasoned programmers, architects, and system designers who are passionate about their craft, using tools, techniques and patterns that enable them to perfect it while remaining pragmatic and grounded. But hey, don't blindly trust my word, go see for yourself - open ClojureTV YT channel, watch their presentations and draw your own conclusions.
- KingMob 2y agoNot the OP, but usually, when people talk about type safety, they're referring to some flavor of static typing, not strong typing. Very few languages still in use in the modern era are still weakly-typed. My personal take is that while a lot of type systems can be overblown, nil-punning is not a sufficient substitute for optional/maybe types.