There are some very sharp Computer Scientists who believe static typing is unnecessary. Joe Armstrong (co-designer of Erlang) once said: "a type system wouldn't save your system if it were to get hit by lightning, but fault tolerance would"
There are some very sharp Computer Scientists who believe static typing is unnecessary. Joe Armstrong (co-designer of Erlang) once said: "a type system wouldn't save your system if it were to get hit by lightning, but fault tolerance would"
I have the same attitude toward overly permissive type systems that I do toward the lack of memory safety in C: People sometimes say, "if you do it right then it isn't a problem," but since it objectively IS a problem in practice, I would rather use the tool that eliminates that problem entirely than deal with the clean-up when someone inevitably "does it wrong."
Long story short, a particular machine that joined the cluster that morning had some kind of CPU or memory flaw that flipped a bit sometimes. Our Elixir server was fine because we were matching on valid values. Imagine a typed language compiler that makes assumptions about things that "can't" happen because the code says it can't... yet it does.
The only way to tolerate that kind of error is checksums on your data, and I don't think any language has that kind of redundancy built in.
For example
match parseFoo json with
| Ok foo ->
process foo
| Error message ->
print message
This will skip bad messages and be statically typed in the valid case.As such fault tolerance does not guarantee that you MRI scanner does not kill your patients.
You likely want both.
Elixir's seamless pattern matching paradigm, IMO, largely negates the need for strict typing. If you write your function signatures to only accept data of the type / shape you need (which you are incentivized to do because it lets you unpack your data for easy processing), then you can write code just for the pretty path, where things are as expected, and do some generic coverage of the invalid state, where things aren't, rather than the norm in software development of "I covered all the individual failure states I could think of". This generic failure mode handling, too, greatly benefits from dynamic typing, since in my failure state, I by definition don't know exactly what the structure of my inputs are.
However,elixir depreately needs proper types. IMHO the needs for types are in no means negated by pattern matching, and I also see hints at why you would say so.
> If you write your function signatures...
The point of types is worry less refactoring.
If you work at a place where you can define the arhicture for the entire lifecycle of the application without ever needing to Refactor, then sign me up! I want to work there.
I see this story on an on: some hacker makes a language, they hate types because they want to express themselves. The languages gets traction. Now enterprise application and applications with several devs use it and typing gets essential - types will then gradually be added.
What? Elm was literally the result of a single grad students side project - elm incorporates both a sound type system and FRP.
This has nothing to do with time. It was a decision not to support it.
What you are describing is a runtime concern that has nothing to do with types.
These issues are neither amplified nor alleviated by using types.
Very opposite the Go model, btw.
Erlang/Elixir's approach is to simply say, "It's gonna fail no matter how many precautions we take, so let's optimize for recovery."
Turns out, this works fantastically in both cellphone signaling, which is where OTP originated, as well as with webserving, where it is perfectly suited.
It just does not catch logics errors.
in other words, any error that doesn't occur right at start can be recovered from at least for all those operations that do not depend on that error being fixed.
Both because that memory leaks are normal is types languages - and does usually not matter in most serious applications - and because this class of errors is usually not what types catch.
Types have value when you 1) refactor and 2) have multiple people working on a code base.
The error you see when you don't have types is something like a BadArityError.
It WILL log the error, with a stacktrace, so you have that going for you
Note that even with typing, you cannot avoid all runtime errors
Also note that this tech was first battle-tested on cellphone networks, which are stellar on the reliability front
You get zero help and punished hard for failing.
I never did track down the last spot where we screwed that up. This was a system we shifted from statsd, so the offending callers were either working by accident or only killing some data points for one stat and nobody noticed.
So then OpenTelemetry.js had to start sanitizing its inputs and not assuming the compiler should catch it. I still think it odd that something called “.js” was actually “.ts” under the hood.
Getting an error on "Value: " + 2 is very annoying if that's what you wanted to do.
The solution here is Static typing, not Strong/Weak typing.
I don't want to look at TIOBE, so let's look at the stack overflow survey from 2024. https://survey.stackoverflow.co/2024/technology#admired-and-...
Strong + Static: TypeScript, Java, C#, C++, Go, Rust, Kotlin, Dart, Swift, Visual Basic, Scala
Weak + Static: C
Strong + Dynamic: Python, Lua, Ruby, R, GDScript(*)
Weak + Dynamic: JavaScript, PHP, Matlab, Perl
At this point I'm reaching into the low percentages. I think it's pretty clear that Strongly + Statically typed languages are massively over-represented on the list.
Both Strongly and Weakly Dynamically typed languages are similarly represented.
Note: I'm open to editing the comment to move languages from and to various categories. I haven't used many of them, so correct me if I'm wrong.
not anymore. they were very popular in the industry at one point. very few other languages have so many independent implementations as smalltalk and lisp. a testament to their wide spread use in the past.
Strong + Static: TypeScript; Weak + Dynamic: JavaScript
that doesn't make sense. typescript is javascript with types, it can't be both strong and weak at the same time.
but i believe we have a different definition of weak. just because javascript, php and perl have some implicit type conversions doesn't make them weakly typed. i believe it takes more than that. (in particular that you can't tell the type by looking at a value, and that you can use a value as one or another type without any conversion at all)
C is weakly typed, it was always a major criticism, C++ too i think (less sure about that).
once you correct for that you will notice that all languages in the strong and static category are less than 30 years old and many are much younger. (java being the oldest. but there are older ones like pike which is also strong and static and goes back to 1991)
the strong and dynamic category goes back at least a decade more. (if you include smalltalk and lisp)
what this does show is that static typing has experienced a renaissance in the last two decades, and also the worst is really using any form of weak typing.
i still don't get what makes strong and dynamic a bad combination, other than it's bad because it is not static.
I know that there are discussion about what strong vs weak even means, but I think most people would place the weak distinction way above yours on a possible weak-strong spectrum.
C can certainly be argued to be weak. My understanding is that it's mostly due to pointers (and void* especially). C++ is much better in this regard. I mostly just did not want to add a Weak + Static category just for one language.
Well, now that you've defined Strong to also include all of the languages I consider Weak, then yeah, no issues at all.
but the interesting question is really the one posed at the beginning. what makes strong but dynamic a bad combination?
i think we agree that weak is bad. implicit type conversions like 1+"2" range from the annoying to problematic and dangerous. if we eliminate weak that only leaves strong and static vs strong and dynamic.
i agree that strong and static is better in most cases, type declarations help, and pike the language i use the most myself which is somewhere between python and go, has powerful types that are a joy to work with, but for comparison in typescript types come across as more annoying (in part because they are somewhat optional, and because they get lost at runtime, so they don't help as much as in truly typed languages) but strong and dynamic has shown to be a solid combination, especially with python and ruby. so i don't feel the combination is as bad as you seem to suggest.
Sure, Smalltalk isn't, but Lisp is a different story. In this context I assume we all mean to say "Lisp" and not "Common Lisp" specifically.
Lisp (as the entire family of PLs) is quite massively popular.
Standard rankings have major blind spots for Lisp measurement, they miss things like, for example, Emacs Lisp is everywhere. There's tons of Elisp on GitHub alone, and let me remind you, it's not a "general-purpose" language, its sole function is to be used to configure a text editor and there's mind-boggling amount of it out there. AutoLISP is heavily used in CAD/engineering but rarely discussed online. Many Lisp codebases are proprietary/internal. Also, dialect fragmentation artificially deflates numbers when measured separately - many rankings consider them different languages.
If you count all Lisp dialects together and include: Emacs Lisp codebases, AutoLISP scripts in engineering, Research/academic usage, Embedded Lisps in applications, Clojure on JVM and other platforms - babashka scripts, Flutter apps, Clojurescript web apps, etc;
...Lisp would likely rank much higher than typical surveys suggest - possibly in the top ten by actual lines of code in active use.
Log lines are whatever, but a system that goes into a crash loop or fails on most requests isn't great.