The above discussion about dynamic vs static typin...
# thinking-together
d
The above discussion about dynamic vs static typing is very interesting. I personally favor static typing (and many here seem too also). But, recently, I've become curious about what's making the Clojure, Elixir, etc people so damn happy. Or, in other words, I'd like to hear a steelman of "dynamic typing is awesome". Can anyone help?
d
The thing that’s essential to the Clojure experience for me is the interactivity of it all. I connect via a REPL and can introspect and grow my program over time in a way that’s very organic and satisfying. I don’t think this experience precludes static typing, but Lisp tooling for this is very advanced already, and considered a first class, essential feature.
👍 1
I also really like that there aren’t crazy abstract datatypes or classes - everything is just lists, sets, maps, or vectors, and once you learn the core library, you can do anything on those that you need to do.
d
Your post reminded I wanted to add something to this, at least for Clojure and Elixir, are they awesome despite not having static typing? Or, are there really essential features of these two which is definitely impossible with static typing?
Along these lines, I was looking for something like Elixir but with static typing. But, all the projects which fit the bill (running on BEAM) are immature (it seemed to me). I know for the Lisp case there is Hackett, Typed Racket, more?
d
I don’t know, and super curious about this as well. I know typed lisp is really, really hard (at least, it’s hard to type something like
eval
). I don’t know if its possible to have all my fun Clojure features with a static typed language. I really love the simplicity of Lisp syntax, but types do seem really neat - it would be great if I didn’t have to choose only one.
I’ll ask on the Clojure slack.
d
Good. Nice. I mentioned those two, but unfortunately I don't know enough about all of this to read their docs and evaluate it properly. Hopefully someone will swoop in here and help us 🙂
d
I'm fairly sure being dynamic, among other things which are equally important, was a design goal from the start.. I can't speak authoritatively on the subject, but thats always been my impression. Its highlighted right on the main site https://clojure.org/
My frustration on long debts about static vs dynamic is that those other important aspects quickly get swept under the rug. Things are often more then the sum of there parts.
everything is just lists, sets, maps, or vectors, and once you learn the core library, you can do anything on those that you need to do.
This is part of the equation, Rich has really put his foot down and said these are the Types you need. He has constrained the language in such a way that its easy to use those and harder to make others. I think this is part of the philosophy behind "simple made easy" It seems static typing proponents are looking for strong guarantees and Clojure offers them by limiting types to those which have proven utility and synergy with the physical world while exposing high level abstractions over them. This allows you to offload the burden of juggling the types and compose with confidence knowing everything can be used as a collection.
f
on what dimensions is
clojure.spec
a static type system, vs not a static type system?
d
predicates seem like a fundamentally different primitive than types. But that’s just an intuition.
f
Not to go all #CKC6FM9DF here, but one way to look at a type is as a set of all possible values of that type, and a potentially-infinite set is equivalent to a predicate…
d
i'm not qualified to answer that 🙂. Rich has tons of material out there on it and that question has been tackled quite a bit in other forums by people with a stronger background in both camps. I actually worked under someone who created a library that combined writing function with specs. I still have no strong opinions one way or the other on that applying them that way. I think its important to be constant in that regard.
potentially-infinite set is equivalent to a predicate…
what do you mean? i think of predicates as defining set membership. So in that regard, i feel like they are the same as a Type.
f
Or I guess looking at it from another angle, haskell lets you make container types which are neither lists maps sets nor vectors, while clojure "types" insofar as they can be observed to naturally occur, are all going to be subtypes of one of those.
d
What do you mean by subtype? Are we calling a function a subtype?
f
Right, the primary use of static typing is to ensure you don't perform operations the wrong types of things; what does "wrong" mean? Well, if you pass a value to a function whose argument has a type annotation, that annotation is acting as a predicate on which values are and aren't valid to pass into that function
In dynamic languages I think I mean the
instanceof
operator, or structural equivalence insofar as the types are observations about the shapes of maps which are not explicitly reflected in the program text(though they can be for e.g. React.propTypes) In static languages, this is explicitly enforced by the compiler, as all those relationships are explicitly reflected in the program text; in theory anyway
Another plausible definition is the "duck typing" one: if I pass a value somewhere expecting another value, does anything go wrong? If not, both the values are of the implicitly defined type "has a
.then
method" or such; even if there are more specific (sub)types that the values individually inhabit(
browser.HTTPPromise
and
npm.fancyforms.DialogDismissedPromise
respectively for example)
d
I dont believe it's idiomatic to create new types in clojure for most things. l. The intuition is that, like the existing types, it should be a data structure e.g a tree and your using it because of its performance characteristics. ... Clojure isn't using what is commonly thought of as duck typing. https://stackoverflow.com/questions/43840366/type-system-in-clojure
f
Every language has at least one definition of "type", and they don't perfectly line up! In a specific context, you can use a definition like "anything in haskell declared with a
data
keyword" or "anything in Java/Clojure declared by a
class
or
interface
keyword", but obviously those two are not completely compatible when trying to translate code or concepts
g

https://youtu.be/YR5WdGrpoug

is a pretty good summary of why rich hickey doesn't want to deal with static types as they work now and I think alexis king (lexi lambda) has an unfinished blog post about how it may boil down to issues with nominal vs structural typing
d
niceeeeeee. looks like what I'm looking for
d
So far on Clojurian’s slack, no one has listed any features that are impossible to achieve in typed languages (transducers came up as something very difficult to achieve in static languages, but there were a few counter examples of how to do it in Scala, Haskell, etc.). The other thing that came up was how nil punning is used in Clojure in a way that can be resilient to change in systems, but I think this whole idea of optional data is hotly debated and in flux in the Clojure community (as evidenced by the above Rich Hickey talk given last November). I think the above Gist is the best summary of the Clojure mindset on types I’ve encountered, which is surprisingly much less “against static types” and much more “for openness to extension”.
2
g
yeah I actually think this is a sensible way of resolving the debate—ie nobody is saying "PLEASE LET ME ADD STRINGS TO INT FOR THE LOVE OF GOD I NEED IT AND IT'S BUSINESS CRITICAL"–it's more like, on the static type side we've all been burned by runtime type errors but on the dynamic type side a lot of people have been burned by types forcing them to change a lot of code during of relatively simple API upgrades (it's midnight for me so might not be super clear)
y
https://gist.github.com/halgari/f431b2d1094e4ec1e933969969489854
Many known static languages like Java, C++, Haskell have nominal type system which require a lot of ceremony to declare types, and functions specify exactly what types they get or you do a lot of work to define interfaces for has-x, has-y. But looks like languages with structural type systems, like PureScript, would fit well the needs he describes.
d
I've been watching Rich Hickey videos, to see his take on static vs dynamic typing. I like this video:

https://www.youtube.com/watch?v=2V1FtfBDsLU

Hickey's concerns about static type systems are not fully addressed by structural type systems alone. There is a lot more to his position than just "nominal types are bad". I hypothesize that Hickey's criticisms of static typing might be addressed by a soft type system. For example, see "A Practical Soft Type System for Scheme": https://www.researchgate.net/publication/2484820_A_Practical_Soft_Type_System_for_Scheme
The soft typing paper looked promising. It seems to fix the "intellisense" problem, and to allow you to flip a switch to show or hide type errors, but if you hide type errors, then it's exactly the same thing as dynamic typing. A more recent paper, "Practical Optional Types for Clojure", claims that soft typing "has proved too complicated in practice". http://homes.sice.indiana.edu/samth/typed-clojure-draft.pdf
d
@Doug Moen what are his criticisms? Mine are based off java, which I know is limited.
d
@Drewverlee I think the problem is that the types that are automatically inferred by soft typing can become very complicated. Which is a problem if the user has to look at an inferred type and understand what it means. But I think that proponents of dynamic typing will make the same criticism of any attempt to impose a static type system on idiomatic dynamically typed code. The general criticism is: if your starting point is a dynamically typed language, and the programming idioms used by such a language, and if you impose a static type system, then you add a lot of complexity and friction to the development process. In many cases, this creates a net loss of productivity, and the addition of static typing is simply not worth it.