This has been said by lovers of types since ages past.
It’s probably wishful thinking, but what a good wish. Silent failures, the ever-present possibility that something is horribly, horribly wrong inside your program, are scary. And they should be scary. When people want to go and write a daemon in Ruby, we should be scared. Tests are not enough; neither are types. Each is a necessary but insufficient condition for confidence that our programs actually do what we want. Types provide a lower bound on failure, by saying “these sorts of failures do not happen in this program”, while tests provide an upper bound by saying “we did not find these types of failures in this program.” They provide different guarantees, and have different quality trade-offs, and it is utterly nonsensical to imagine you can trade types for tests, or tests for types. They go together. In a unityped/untyped language, you only get one. Maybe, if there’s gradual typing, you get a fascimile of the other, but there are a number of decisions made in unityped language that confound and complicate the notion of type checking. Indeed, the world of gradual or soft typing research has confirmed that adding types is difficult, and not to be done lightly. So if we’re going to make a new language, we most definitely want one with strong static guarantees and good facilities for testing, so that we can have as much confidence in correctness as possible. That’s the best way forward, if not the only way. (As an aside, it shouldn’t be surprising that I am a strong Rust supporter.)
This is my bet: the age of dynamic languages is over.
I wouldn’t take those odds.
A year or three back I would have said I need Ruby.
I sometimes need C/C++ for low level / fast tasks… but for getting things done I need Ruby.
Now D is slotting into a lot of places I’d previously have used C/C++ AND/OR Ruby.
And it’s better than the lot of them.
D only makes me specify types when it actually helps, and allows me to specify types “maximally weakly”, but instantiates to strict type checking “as compiled on the day”.
So actually I agree with him. I foresee the day I will write my last program in a dynamically typed language, and it may not be as far away as you think.
That may mark the end of dynamic languages for you, but not for the world. I have a hard time seeing dynamic languages going away in the near future.
If you get the advantages of both (static and dynamic) languages in a single language without the disadvantages of either… Why, apart from buckets of Legacy code, wouldn’t you shift?
If you get the advantages of both (static and dynamic) languages in a single language without the disadvantages of either
What wonder-language are you referring to?
D is getting close to that point…
If I look at the reasons I use Ruby…
Guess what? D has all of that these days.
D’s GC isn’t quite up to Rubies standard (yet?), but on everything else D meets or exceeds Ruby.
And then adds C like “as close as you can get to the metal without burning yourself” fast.
And then adds C/C++ like (and better) type safety (without the typing fluff).
And then adds C++ like, but hugely easier generics.
D has a large addon library “dub” collection, growing but not yet exceeding Rubies gem collection.
Dynamic Languages are nice in that a lot of stuff “just works with anything that quacks”.
In D you write “generic by default”, and it “just works with anything that quacks”.
AND the compiler will tell you at compile time if anything you feed it doesn’t quack!
And then allow you to add a custom “Sqvack!” trait method if you need it for strange sounding duck like things.
D has taken the C++ iterator idea and the Ruby Enumerator idea and run way beyond both with the Range concepts.
Ultimately D’s short comings seem fixable and likely to surpass Ruby on every measure… I’m not sure Rubies shortcomings are fixable, as a number of design choices are too deeply baked into the language.
We’re nearing a tipping point. Not there yet, but getting nearer.
Good run-down, I think I’ll be trying out D in the near future. Thanks! :)
C++ templates quack as well: into error novels.
I’ve found that a lot of what I used to write in Python translates directly into Scala.
Show me a statically-typed language that can boast the reliability and maturity of Erlang/OTP and we’ll talk.
I very much appreciate Erlang, but if you want to refactor a function, by renaming the function for example, or renaming a variable used in the function, or adding a parameter, how do you make sure you dont’t have a typo somewhere?
You run dialyzer, and it tells you.
If you’re using a static analysis tool then you’re working in a statically-typed language, you’re just brushing the static types under the carpet. What advantages do you get from having dialyzer be external to the rest of the language?
Well yes, obviously it is a continuum. However, I’m not aware of any self-described static languages that use success typing as their inference strategy. Maybe one exists; if so, cool!
exact same experience here.
D is a bit rough around the edge and missing lots of libraries.
but its has all the right features to make you insanely productive while still allowing maximum performance if needed.
D is very cool and I’m going to use it for my next personal project, but I simply can’t imagine the dynamic languages are going to go away. I can see their use diminishing as various projects mature (read: migrate to something more solid), but they are still incredibly useful for prototypes and working where the notion of “specs” (and specifically the initial data model) is essentially a joke.
That’s the really interesting thing about “Generic All The Time”.
Normally if I write a function in “Concrete/Specific/Strictly Typed all the Time”….
I have to specify a function like…
isExactlyADuck_t myFunc( isExactlyADuck_t duck, isExactlyADog_t dog)
I first have to find and specify the exact types, and they better have a quack and a bark, and it will only work for that specific duck and dog.
In a dynamic language like Ruby I go…
def myFunc( duck, dog)
and it magically works for all things that quack and bark….. but I’ll only know that it works if I run that… and I will only know that for the particular duck and dog a passed in for that particular run.
In “Generic All The Time” I go ..
duckish myFunc(duckish,dogish)( duckish duck, dogish dog)
While I’m writing myFunc I needn’t even know what duckish and dogish is now… or in some future.
…but as soon as I invoke…( both in my rapid prototype and in my final production)
auto muck = myFunc( mallard, mutt);
the compiler verifies mallards quack and mutts bark and automagically grants “muck” the type mallard.
Even though I want it to be true, I’m not sure “the age of dynamic languages is over”. Look at Elixir, which is new and relatively popular in spite of its lack of types.
julia likewise. in fact, in julia’s case the dynamic nature is a plus, because it lends itself to quick exploratory programming.
Yeah, I don’t think the age of dynamic typing will be over until you have a typed-language that’s as simple to program as a dynamically-typed language and as simple to learn as a dynamic language and possibly even as fun as a dynamic.
I mean, I love the flexibility of Ruby’s syntax and reflexion. I mean, now I understand what a horrid messy everything Ruby-ish leads to but when I started Ruby, it felt like freedom - I had three or four other languages under my belt at that point.
I would agree with this. I don’t think we’ll ever get to an Idris paradise, but I think languages like Go will be the norm: weak type systems with interfaces, suitable for catching typos.
As an enjoyable smug aside, however, the SBCL Common Lisp compiler catches a variety of things at compile-time. I’ve not dug deep into pushing its edges, but it has a profound advantage over other dynamic languages… :-)
The only thing I really do not like in CL is it being a Lisp2. It makes me think.
I like the shape of the Lisp2 wart. It offers fluidity in comprehension and irritation in having to type FUNCALL yet again.
Think about what?
I’m on the opposite side of the fence: it offers fluidity and avoids having me think about needless details.
I don’t know if people share CL under the dynamic languages (I would, with options for more stricter checks) but if they do: they’re not going away if only because people prefer the development workflow they offer.
I don’t think we’ll ever get to an Idris paradise, but I think languages like Go will be the norm: weak type systems with interfaces, suitable for catching typos.
I sure hope not. That sounds like the worst of both worlds - all the effort of a good type system but few of the benefits.
Well, I am being pragmatic - the most popular languages as far as I can tell conform to the ‘weakly typed’ paradigm (C, Go, Java), and powerful types are considered to be ‘egghead’ languages (highly regrettably, but… eh…).
I think the ideal triplet would be something like Rust + Haskell + Common Lisp, but that is super nerdy of me.
I think you’re in a real bubble if you think Go’s a popular language. TIOBE puts it at #48, below Haskell or Lisp.
Java’s typing looks weak now but at the time it was a huge safety improvement over the C/C++ it displaced. I think any new language will have to have a compelling advantage both over Java and over Python/Ruby/etc. And I don’t see that happening for a Go-like language.
The RedMonk study brings a different view on popularity of programming languages: https://redmonk.com/sogrady/2015/07/01/language-rankings-6-15/
I think the data sources used by RedMonk are more pertinent than the ones used by TIOBE.
And I don’t see that happening for a Go-like language.
I very much agree that Go’s type system is simple, and maybe even simplistic. It’s sometime a drawback. But that’s just one aspect of the language. Go offers “compelling” advantages in other domains, for example: built-in concurrency, built-in garbage collection (unlike C), local type inference (unlike Java), close to C performance (unlike Python or Ruby), static binaries (unlike Java), control over memory layout (unlike Java or OCaml), fast compilation (unlike C++ or Scala), short language specification (unlike C++ or Scala), interfaces and struct embedding, great standard library, great tooling (formatting, linting, refactoring, documentation…), etc. That’s why people use it.
Although it’s great to see some love for strongly typed languages, I believe there is room for both dynamic, and more strongly typed langs. I think Clojure, and younger efforts like Nim, or Crystal show that there is an audience for optional certainty to reuse your phrase. I know that Ruby’s plans for the future also include optional typing, but the end is not near. :)
I really agree with you here.
One of the things I want when prototyping out how I think something should work is a dynamic language that I can still run and play around with. The repl workflow is very powerful for understanding how an API will “feel” to a client, etc. Guile + geiser and sbcl + SLIME make this just a dream.
But once it’s barely working, I generally want types immediately to clean things up and remove warts. Ideally I’d have guile + super high end typing (agda-style dependent typing) that only got enabled in a module when you started using it. I realize ironically that this may be an uncomputable wish, but it’s what I dream of.
Nim + Crystal are really great suggestions, I think I’m gonna spend more time learning Nim, but I strongly dislike the syntax and their compiler efforts so far.
I used to think this, but using the Checkers Framework and TypeScript I found that it just doesn’t work. 90% typing gives you ~0% of the benefits; if you can’t rule out these classes of error then you end up needing just as much test coverage for a given level of confidence as you would in a purely dynamic language.
I still use plenty of Python, and feel pretty productive in it. Conversely I love the confidence I have my strongly typed Haskell and (to a lesser degree) Scala code.
But this post echos my experience with Clojure & Ruby. My feeling is that dynamic languages are like financial leverage. You can pay up front by submitting to the discipline of strong static typing, or you can pay maintenance costs later with a high testing and bug-fixing burden. There are appropriate (and inappropriate) reasons for choosing either one. Just be conscious of that choice and your reasons for choosing.
But this post echos my experience with Clojure & Ruby.
I agree in some contexts, but It’s a shame that he limited the discussion only to dynamic languages that have nil. Most of the problems he mentioned are much less prominent in languages like Racket and Erlang that simply omit nils entirely, while many static languages have type systems that don’t even attempt to solve the problem.
I don’t know if it’ll ever be either/or, I think we’ll see some core code (well-known, doesn’t change much anymore) be very strictly typed, and less-strictly (optionally in some cases, with tests in others) in the faster-moving areas. I very much like the idea of strict-typing when I need it and can take the time to come up with the “proofs” (types as proofs), and a bit more dynamic in places where I’m still using evidence (tests) instead of proofs. (Jessica Karr, aka ‘jessitron’ solidified my thinking on this in her QConSF talk about Clojure + Prismatic:Schema last week.)
This discussion feels like everyone takes the inflammatory title, projects their opinion and doesn’t read the post. Whether you agree with the premise and the conclusion or not, it is a gem of thinking about software.
The most interesting part is explicitly talking about “uncertainty”, which you should immediately put into your vocabulary.
I do, however, not agree with the conclusion that static languages are the only way to provide certainty. For most of the examples the author gives (maps and arrays everywhere), an implementation strategy using types instead of maps and arrays can be derived, even in the languages described as “dynamic”. Static - especially strong static - languages suffer from similar problems creating uncertainty, though, especially for beginner programmers: implementing stuff “just to make it work for the compiler”, or, at worst, resorting to “stringly typed” interfaces or even, well, HashMaps and Arrays.
The advantage of dynamic languages is that they are a bit like glue: not as clear and structured as the fixed parts, a bit messy to use and you have to clean your fingers afterwards, but they can easily pose as everything. Ruby, for example, for me, was often a language that can pose as a mediocre stand-in for any other languages it interfaces with.
Talking about uncertainty is, however, a good way to judge what approach to take for different implementations. I love environments where I have both tools at hand: a rather static language, with a dynamic one on top. For me, one of those examples is Java and JRuby. Java for the hard parts, JRuby for the parts where I’m okay with missing something and just crashing, but want to have a rather free and declarative language.
 especially in Ruby, which - due to strict handling of types with no automatic casts - actually lends to “types everywhere” approach. Sadly, the author dismisses the language outright.
 one of the examples, Ring, sadly seems to copy that strategy from Rack and WSGI, where both have figured out over time that this was a bad approach.
I don’t know if dynamic languages will be done for awhile.
For me personally, I’d prefer to avoid them as much as possible. They’re a strong signal that the firm looking to hire me isn’t doing the work I’d necessarily be interested in.
I appreciate that. There’s quite a lot of fields where that sounds very true.
I hope it doesn’t sound too entitled or elitist. But the article’s discussion of languages encompassing a set of values is absolutely spot on. I am happier when my values are reflected in the tools that I use. Although that is not always the case, it is important to seek out places that make it possible, rather than always precluded because insert grown-up-sounding reason here.
No, doesn’t feel like that at all. I’m very fine with “I would like to use language A or tool B at my job, because it is my taste”. Also, profile-building is a thing and still very attached to the technology you use, especially the language.
As long as you don’t go running around and get all ranty about people not having seen the light and how bad they are and how their company will fail (which happens all too often), preferences are a very real thing.
I disagree. I generally find myself agreeing with the OP (static is better) but I think that it’s phenomenally easy to conflate one’s own trajectory through languages with a more general trend in programming and its needs.
As discussed, dynamic typing test drives very well, but it can burn you at scale. All of that said, the existence of a type system is not the only thing that matters. I’d rather work with competent Clojure programmers, by far, than with shitty Go or Java developers. I’ve seen companies grind to a halt due to shitty engineering in dynamically typed languages (cough Ruby on Rails) but I’m not convinced that it was ever Ruby’s fault. Programmers tend to blame languages, as if tools themselves could be held responsible for shitty engineering, because they’re often confrontation-averse and refuse to look the real problem (shitty management, unreasonable deadlines, mediocre programmers) in the eye.
Also, the OP’s ugly null problem was in Scala, which is more static than most programmers want to go. (We can argue about whether “most programmers” have the right idea, but that’s a separate issue.) I like Haskell much better than Scala, but getting average-quality (or lower) engineers to even consider, much less accept, Haskell is such an uphill battle, politically, that I tend not to have much faith in the idea that you can fix a broken company by changing to a strongly typed language.
I don’t think that we’re at “the end” of dynamic languages. People will still be using them 20 years from now. The exciting languages might be statically typed, and perhaps dynamic languages are going to be “dead” in the same way that Java has been “dead” for 10 years, but that doesn’t mean all that much in the real world.
Besides, look at the success of Python. Is it an exciting language? Not really. It’s not terrible, either, although the 2/3 split is pretty damn troubling. It’s a language that, for the most part, gets out of your way (even when you want it in the way, as with a strong type system that prevents low-quality engineering). It seems to be good enough for many purposes, and you can find pretty much any library in it, which is why it’s winning even in, say, data science, where no one would have expected it to do so.
Programmers tend to blame languages, as if tools themselves could be held responsible for shitty engineering, because they’re often confrontation-averse and refuse to look the real problem (shitty management, unreasonable deadlines, mediocre programmers) in the eye.
But tools have affordances, and some are better at encouraging good behavior than others.
That’s absolutely true– from personal experience, I know that even I write better code when I have a statically typed language like Haskell– and I think that language choices can be symptomatic. If a company uses only Java and hasn’t even allowed its better engineers to experiment with Scala or Clojure, that’s a bad sign about the company. It’s not that Java itself is ruining the company– it’s a shitty language, but it’s still just a tool– but what the Java-only attitude says about the place.
The issue, for me, is that there’s so much incompetence in software management right now, and it’s so severe and overwhelming, that the language wars are just a small sub-battle. Yes, I’d much rather use Haskell than Ruby or Python or C++, but sometimes it takes all of my emotional energy and political capital just to keep out that humiliating “Agile Scrotum” garbage.
Python absolutely was exciting at the time (20+ years ago now). The cleanest syntax ever! A language that supported every paradigm but was still cleanly put together! A language with the underlying elegance of TCL but without the superficial ugliness of TCL!
The language that brings good typing to the masses may be similar (Ceylon? Idris?). It probably won’t be the first language to come up with the features. But while the wheels of progress turn slowly, they do turn.
How on earth could you write a post like this without mentioning Dialyzer? The mind boggles.