5 ms·
The point is, types give you an option to encode invariants at compile time. You can choose to use this to your advantage, or not use it at all(use ByteString f
by wz1000 9y ago
The point is, types give you an option to encode invariants at compile time. You can choose to use this to your advantage, or not use it at all(use ByteString for everything).
With dynamic types(or just one type), you don't even have the option to do this.
- brandonbloom 9y agoExcept I really don't have that choice because the language and library design matters. If I chose to use ByteString for everything, I'd first have to implement Tcl in order to get anything done. But, yes, you're right, most dynamic languages lack good tools for stating invariants and checking them early. I would like to see that change. However, I'd rather the solution account for runtime dynamism, extensibility, and partiality. We're _slowly_ getting there with more and more advanced type system features. It's time to take that knowledge and repackage it at the foundational level of typed languages.
- didibus 9y agoThere's just one type at compile time, but many more at runtime. This is still a strongly typed language. The only problem is our static analysers are too dumb to prove things without providing ample explicit hints, or changing the way we code to restrict certain ambiguities that it can not resolve at compile time. Haskell has chosen to try and push the boundaries of such static analyzer, but there's still limits, and it can't infer everything, and still restricts certain designs. I admire it for its efforts. Clojure has a different strategy, it creates a new time, REPL time. So you can test your types at REPL time. Not when it compiles, but a little before it runs. It won't prove what you don't try though. So in practice, its using a statistical model where the programmer is the heuristic. You best guess the edge cases, and try them at REPL time. This will not catch all static errors, but will also catch some runtime errors. So it creates a disjoint set of errors that it catches. This is a trade off. Static types and REPL time will catch some of the same things, but also different errors. Now both adding static type info, and doing REPL time testing comes to a cost to the programmer. Its one more thing we have to do. Some like me, fond more value most often at the REPL, it helps me explore and innovate my code, and is just more fun to me. I also prefer the kind of bugs it catches. Others think the opposite. What most people seem to agree on though, is that doing both is way too much effort. That's why you don't have REPL time be a popular activity in Haskell, or core.typed be popular in Clojure.
- wtetzner 9y ago> That's why you don't have REPL time be a popular activity in Haskell Is it not a popular activity to use the Haskell REPL (ghci)? I though it was pretty common to use it when developing code, though I admit I don't have any hard data.
- brandonbloom 9y agoThe Haskell REPL is pretty good for a static language, but the experience is dramatically different to how a Clojure programmer would use want to use it. To be fair, Node and Python also have totally not usable REPLs for this style.
- tome 9y agoIf no other language has any functionality similar to how Clojure does things then I think we'll need references to explanations or videos before we can even begin to understand your claims!
- brandonbloom 9y agoClojure is following in the tradition of lisps that do this right. The important bit is the extra indirection on top-level names. I wrote more about it here a long time ago: https://www.brandonbloom.name/blog/2012/12/21/the-nodejs-repl-is-broken/ https://www.brandonbloom.name/blog/2012/12/21/the-nodejs-rep... Also interesting is the other end of the spectrum: Forth. Instead of mutation, offers snapshots and restores of the “dictionary”. See this video: https://youtu.be/mvrE2ZGe-rs https://youtu.be/mvrE2ZGe-rs
- tome 9y agoI don't fully understand what you're getting at. It would have been nice to see no examples with code entered at a REPL and the results, in both JS and Clojure, say. Are you saying that you want to be able to make bindings that are refreshed on REPL reload? For example if I have a file that contains x = 1 and in my REPL I write y = x + 1 then I change my file to say x = 10 and reload the REPL then y is 11?