Eric Normand writes and podcasts about Clojure, functional programming and type systems.
HN commenters recommend his podcast and link his post on Clojure and types as the best argument they've seen for dynamic types.
Not who you are responding to, but the common idea that static types are all win and no cost has become very popular these days, but isn't true, it's just that the benefits of static typing are immediately apparent and obvious, but their costs are more diffuse and less obvious. I thought this was a pretty good write up on the subject that gets at a few of the benefits https://lispcast.com/clojure-and-types/
Just to name some of the costs of static types briefly:
* they are very blunt -- they will forbid many perfectly valid programs just on the basis that you haven't fit your program into the type system's view of how to encode invariants. So in a static typing language you are always to greater or lesser extent modifying your code away from how you could have naturally expressed the functionality towards helping the compiler understand it.
* Sometimes this is not such a big change from how you'd otherwise write, but other times the challenge of writing some code could be virtually completely in the problem of how to express your invariants within the type system, and it becomes an obsession/game. I've seen this run rampant in the Scala world where the complexity of code reaches the level of satire.
* Everything you encode via static types is something that you would actually have to change your code to allow it to change. Maybe this seems obvious, but it has big implications against how coupled and fragile your code is. Consider in Scala you're parsing a document into a…
> Questions such as yours makes me realize that a lot of go developers don't even understand what is the purpose of generic programming.
While this sounds a bit condescending I know exactly what you mean.
There seems to be some sort of "language barrier" (where the language is programming language concepts) between developers from different backgrounds.
Go is currently used in a lot of successful projects, so it gets new developers from lots of places and they are failing to communicate adequately about the language itself. I see three main groups (there may be more!):
a) People who come from C and other lower-level languages: They are introduced to memory-safety, keep a type system that they already know and are comfortable with and in addition get a polished, well-integrated toolchain.
b) People who come from Python, Ruby and other "untyped" scripting languages. These are introduced to native code (wow! fast!), a type system that isn't expressive - but sufficient (and more than they had before), and the same toolchain experience.
c) People who come from higher-level, safer languages including (but not limited to) Java, Haskell, C# and so on. These developers for the most part already had well-functioning toolchains, but they are "stepping down" to a language that is less expressive (okay, for Java-people YMMV greatly) and often end up frustrated.
Now you get conflicts when the c-people have discussions like this with the a/b-people and nobody is happy.
There's an…
Oh yeah GHC error messages are bad. Notice how I said Elm instead of Haskell at the end :). One of the things I dislike about GHC is the wasted potential there that's evident in the compilers for newer languages like Rust, Elm, and Purescript when it comes to errors.
I haven't found a good way of switching on ex-info generated exceptions. I usually end up having to do string matching or key searching both of which feel brittle. There's ways of following patterns within the boundaries of my own codebase (e.g. a custom key I know will always be there), but that doesn't play well with the ecosystem at large because there aren't well established conventions around what's what. I don't want to come off as saying there's a fundamental reason why Clojure couldn't have better error handling. It's not a language level thing but rather a community thing. I think Python is a good example of where the community has coalesced around using specific error types even though it's a dynamic language.
I totally agree with doing validation at the edges of the program and try to enforce that in whatever language I'm writing in. I think this is a common misconception about statically typed FP that shows up in e.g. Rich Hickey's talk about types. It's quite rare for things like `Maybe` or `Either` to actually show up in your data structure (e.g. Rich Hickey's SSN example). You usually end up bubbling the error to the top of your module and deal with it at a module level. The type is just there…
Well, the three key aspects, in my preference order, are:
1. Server repl with editor integrated clients. So your text buffers in your favorite editor is the repl. Look at the gifs here https://atom.io/packages/proto-repl to give you an idea for it.
2. Reifed language constructs. You can read about it here http://www.lispcast.com/reification . An easy example is if you have fn A depend on B. If you change B and call A, A will use new B. That's because the information is still availaible at runtime for A to figure out the latest version of B when calling it.
3. Functional programming / emphasis on small independent code blocks that compose. This is where you hear things like immutability, functions that take functions, purity, side effect free, managed references, etc. Basicly state in Clojure is hard to corrupt. That means if you alter state in your repl, it rarely messes up the full state, allowing you to keep working long sessions with your app state still being valid and usable.
I don't have a link for #3. So I'll give an example. Say you have a map you want to add data too. Say this map is read by something else, but you want to try adding something deeply nested to it. In Clojure, you can try as much as you want, experiment until you succeed to mold the map the way you wanted. The other thing reading the map never saw any of your changes, because it sees an immutable view of it. So after your done, if you use that other thing, it'll still work, because you didn't…
Fundamental difference between static and dynamic: static typing disallows writing a certain set of perfectly valid programs while also having the advantage of disallowing many invalid programs. So the question becomes: how badly do you want to work in that space that is not permitted by static systems?
And that space is where your data itself is highly dynamic. When you just want to represent data as maps, do generic operations on maps, then spit out more maps back to something else. This description applies to many many real world systems, particular in the more business-type domains.
Another space where dynamic really shines is dealing with relational data in a relational way. Relations are just sets of maps, the most natural thing in the world to work with dynamically. In a dynamic language I can just write code that peaks into the map, transforms certain fields, then passes the whole thing on down the line. I don't care what combination of selects and joins got me that relation, and in reality there will be many, I want to reuse my functions regardless. Although this is where more structural type systems can help ease the pain over nominal type systems.
I feel like this is a great blog post talking about the downsides of static typing in a real world system: https://lispcast.com/user-wizard-scenario/. I appreciate that the author has real world experience with both Haskell and Clojure and comes from that perspective.
Ultimately I'd say that if a program can be…
There is a really interesting link between React and Clojurescript in the Om library. There is a great blog entry about Clojurescript and OM by David Nolen "The Future of Javascript MVCs".
http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/
The claim by David is that, "ClojureScript om based TodoMVC looks 30-40X faster than Backbone.js TodoMVC, which means other JS frameworks left completely in the dust".
https://twitter.com/swannodette/status/412033352699744256
There is some more discussion of Clojurescript and Om on Fredrik Dyrkell's blog on "A slice of React, Clojurescript and Om". The big idea with Om is to simplify idiomatic state management with Clojurescript’s immutable datastructures, while still getting all the performance. He has some nice comparisons with JavaScript and ClojureScript side by side.
http://www.lexicallyscoped.com/2013/12/25/slice-of-reactjs-and-cljs.html
On Eric Normand's blog post "React: Another Level of Indirection" he talks about how there are four pieces of the puzzle in ClojureScript Web Development - and Om is the final missing piece:
Problem: Global state management
Solution: Atoms and persistent data structures
Problem: Client-server communication
Solution: EDN (also solved pretty well by JSON)
Problem: Callback hell
Solution: core.async
Problem: Stateful DOM
Solution: React
http://www.lispcast.com/react-another-level-of-indirection
Form your own opinion of course, but these are some interesting claims.