116

I began coding in in Python primarily where there is no type safety, then moved to C# and Java where there is. I found that I could work a bit more quickly and with less headaches in Python, but then again, my C# and Java apps are at much higher level of complexity so I have never given Python a true stress test I suppose.

The Java and C# camps make it sound like without the type safety in place, most people would be running into all sorts of horrible bugs left an right and it would be more trouble than its worth.

This is not a language comparison, so please do not address issues like compiled vs interpreted. Is type safety worth the hit to speed of development and flexibilty? WHY?

to the people who wanted an example of the opinion that dynamic typing is faster:

"Use a dynamically typed language during development. It gives you faster feedback, turn-around time, and development speed." - http://blog.jayway.com/2010/04/14/static-typing-is-the-root-of-all-evil/

25
  • 16
    This question is the opposite of What arguments are there in favor of weak typing?.
    – Nicole
    Mar 18, 2011 at 18:17
  • 8
    @Prof Plum: may I require a proof that there is a hit in speed of development and flexibility ? Since we are talking about a particular aspect Type Safety, using Java or C# would be inconclusive, their way of providing it is NOT the only one... Mar 18, 2011 at 18:49
  • 35
    With diligence in a strict language, you can minimize the "headaches" and then you might even see a speed increase due to IDE auto-completion, code generation, and code hinting.
    – Nicole
    Mar 18, 2011 at 18:53
  • 9
    @Prof Plum: I understand, I don't expect you (or anyone really) to have fully tested every language ever created ^^ The problem is that most of the people I've seen complaining about some specific aspect of programming languages (Static Typing often comes) generally complain about a particular implementation, and fail to realize it. Mar 18, 2011 at 19:01
  • 5
    @Prof Plum, all that blog post really has to say about speed is the bald assertion "Anyone, who has worked seriously with a modern dynamically typed language like Ruby or Smalltalk, know that they are more productive." No actual examples of how, in practical terms, it makes development faster. Mar 18, 2011 at 20:50

20 Answers 20

181

It's sort of a myth that programmers don't have to worry about types in dynamically typed languages.

In dynamically typed languages:

  • You still have to know if you're working with an array, an integer, a string, a hash table, a function reference, a dictionary, an object, or whatever.

  • If it's an object, you have to know what class it belongs to.

  • Assigning one of these types to a variable or function parameter expected to be another type is almost always an error.

  • At a lower level, things like number of bits or signed versus unsigned frequently still must be accounted for if you are populating a TCP packet, for example.

  • You can run into problems where you get a zero where you really wanted an empty string. In other words, you're still debugging type mismatch bugs. The only real difference is the compiler isn't catching the errors.

  • I'd argue that you aren't even saving much typing- , because you tend to want to document in comments what type your function parameters are instead of documenting it in your code. This is why doxygen-style comment blocks are much more popular in practice throughout dynamically typed code, where in statically typed languages you mostly only see them for libraries.

That's not to say that programming in dynamically typed languages doesn't feel more pleasant because the compiler isn't always on your back, and experienced programmers don't tend to have difficulty finding and correcting the kind of bugs that static typing would catch anyway, but that's a completely separate issue from an alleged increase in efficiency or reduction in bug rate, for which dynamic typing is at best even with static typing.

7
  • 14
    I would have to contest the bit about experienced programmers not making/introducing those kind of bugs. Good developers who are humble and acknowledge the possibility of them making errors(and experienced developers are not always like this) are less likely to create those bugs. Mar 4, 2014 at 3:32
  • 24
    Couldn't agree more with "I'd argue that you aren't even saving much typing". You end up documenting types in comments and checking them in your tests, which, if anything, requires more typing and maintenance (after all, you have to remember to update said comments whenever your types change, and more often than not you won't). Jun 29, 2015 at 21:45
  • 4
    We spend much more time at our Python shop documenting types than we save over a verbose statically typed language like C# or Java. It's also worth noting that the newer generation of languages like Go and Rust use type inference, so you're typing "x := new(Object)" instead of "Object x = new Object()".
    – weberc2
    Feb 8, 2016 at 20:54
  • I agree with you when you say dynamic language feel more pleasant, but I don't know why. Do you have an explanation for that? Jul 5, 2016 at 5:27
  • 1
    @JayJayJay Much agreed. They way I avoid these sorts of errors in JavaScript is by writing out assertions for all of my parameters at the beginning of the function. It's a lot more typing than I would face in (say) C#, but a lot less debugging than I would otherwise face in JS. I do the same in Python, but to a lesser extend than with JS.
    – jpaugh
    Aug 2, 2019 at 19:54
134

As the types get stronger, they can help you more — if you use them correctly instead of fighting them. Design your types to reflect your problem space and logic errors are more likely to become compile-time type mismatches instead of runtime crashes or nonsense results.

2
  • 39
    +1! "logic errors are more likely to become compile-time type mismatches instead of runtime crashes or nonsense results": Really good answer! When I take more time to design my types, then the code follows more naturally and it is often correct as soon as it compiles. Designing a type means to understand a domain and its operations.
    – Giorgio
    Feb 24, 2012 at 17:01
  • A simpler and better answer - softwareengineering.stackexchange.com/a/215532/260655
    – MasterJoe
    Apr 18, 2020 at 19:18
80

Disclaimer: I am a type-lover ;)

Your question is difficult to answer: What are those trade-offs ?

I'll take an extreme example: Haskell, it is statically typed. Perhaps one of the most strongly typed languages that exist, in fact.

However, Haskell supports Generic Programming, in the sense that you write methods that work with any type conforming to a certain concept (or interface).

Furthermore, Haskell uses Type Inference, so that you never have to declare the type of your variables. They are statically computed during compilation, much as a Python Interpreter would compute them running the program.

I've found that most people harshing on static typing, were actually complaining about something else (verbosity, pain of switching one type in favor of another), but Haskell exhibits none of those issues, while being statically typed...


Example of brevity:

-- type
factorial :: Integer -> Integer

-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)

Apart from built-in support, it's difficult to get briefer.

Example of Generic Programming:

> reverse "hell­o" -- Strings are list of Char in Haskell
=> "olleh"
> reverse [1, 2, 3, 4, 5]
=> [5,4,3,2,1]

Example of Type Inference:

> :t rever­se "hell­o"
:: [Char]

which can be computed simply:

  • "hello" is a list of Char (expressed as [Char])
  • reverse applied to a type [A] returns a type [A]

Try it out in your browser

16
  • 4
    To play devil's advocate, one trade-off in favor of dynamic languages (at least while prototyping) is that insofar as type declarations can serve the same purpose as some unit tests, they can also solidify interfaces in the same way that unit tests do (though certainly with less overhead). Also, statically typed languages without coercion, while safer, require explicit type casting (particularly when a type isn't generic enough), which can detract from terseness.
    – T.R.
    Mar 18, 2011 at 21:08
  • 8
    I don't know Haskell but +1 for "were actually complaining about something else (verbosity, pain of switching one type in favor of another)"
    – Nicole
    Mar 18, 2011 at 22:08
  • 2
    @Aidan: Haskell is an evolving language. Haskell 98 was an improvement over Haskell 1.4; Haskell 2010 was an improvement over that. Meanwhile, it's worth noting that for most of its life, Haskell's raison d'être was to help explore type systems; multi-parameter type classes are one example of where it succeeded in elucidating a useful type system extension. (On the flip side, functional dependencies are looking to be something of a dead end.)
    – geekosaur
    Mar 19, 2011 at 4:43
  • 4
    @Matthieu: WRT "Perhaps one of the most strongly typed languages that exist, in fact.", I'll see your Haskell and raise you Agda and Coq. (I will grant that it's probably the most strongly typed practically useful language.)
    – geekosaur
    Mar 19, 2011 at 4:51
  • 1
    @Matthieu: Proof assistants are a direct application of the Curry-Howard correspondence, so they are at heart programming languages (albeit with rather limited standard libraries). They're at the forefront of dependent type research because you need dependent types to make good use of the "types are propositions" correspondence.
    – geekosaur
    Mar 19, 2011 at 17:19
39

I like both statically-typed and dynamically-typed languages. The two biggest advantages of type safety to me are:

1) You can often pretty much deduce what a function does purely from its type signature (this is particularly true in functional languages like Haskell).

2) When you do significant refactor, the compiler automatically tells you everything you have to do to keep everything working. When I refactor something in C++, my procedure is often simply a) change the one part I know I want to change, then b) fix every compile error.

1
  • Exactly same with me, and whenever I want to refactor something (I mostly use golang/typescript/java), yeah, those 2 steps are the ones anyone would need. change one part, then fix all compilation error :) perfect answer. Sep 12, 2018 at 0:29
31

Personally, I find that type safety helps me develop faster in my current job. The compiler does a lot of the sanity checking for me almost as I type, allowing me to focus more on the business logic that I'm implementing.

Bottom line for me is that although I lose some flexibility, I gain some time that would otherwise be spent tracking down type issues.

0
21

There are a lot of strong opinions surrounding the debate but obviously this isn’t actually a matter of opinion, it’s a matter of facts. So we should look at empirical research. And the evidence from that is clear:

Yes, static typing is worth the trade-offs — and not just by a bit, but in fact substantially. In fact, solid evidence shows that static typing can reduce the number of bugs in code by at least 15% (and this is a low estimate, the actual percentage is almost certainly larger). That is a shockingly high number: I think even most proponents of static typing wouldn’t have thought that it made such a drastic difference.

Consider this: if somebody told you that there was a simple way to reduce the bugs in your project by 15% overnight, that should be a no-brainer.1 It’s almost the proverbial silver bullet.

The evidence is presented in the paper To Type or Not to Type: Quantifying Detectable Bugs in JavaScript by Zheng Gao, Christian Bird and Earl T. Barr. I encourage everybody to read it, it’s a well-written paper that presents exemplary research.

It’s hard to summarise succinctly just how rigorously the authors performed their analysis but here’s a (very rough) outline:

TypeScript and Flow are two programming languages based on JavaScript that, while remaining otherwise compatible, add type hinting and static type checking. This permits augmenting existing code by types, and then to type check it.

The researchers collected Open Source projects written in JavaScript from GitHub, looked at resolved bug reports and attempted to reduce each of the reported bugs to a piece of code that would be caught by the static type checker of TypeScript or Flow. This allowed them to estimate a lower bound of the percentage of bugs could be fixed by using static typing.

The researchers took stringent precautions to ensure that their analysis wouldn’t consider a non-type related bug as being related to types.2

Compared to past studies, this new study has particular strengths:

  • There is a direct comparison of static vs dynamic typing, with few (if any) confounding factors, since the only difference between JavaScript and TypeScript/Flow is the typing.
  • They perform replication across multiple dimensions by checking both TypeScript and Flow (i.e. different type systems), and by having different people reproduce the (manual) type annotation to fix the bugs. And they perform this across a large number of code bases from different projects.
  • The paper measures the direct impact of static typing on fixable bugs (rather than some more vague quality).
  • The authors define a rigorous model of what to measure, and how, up-front. Furthermore, their description is incredibly clear and makes it easy to analyse for flaws (it’s always good when a research paper opens itself up to attacks: if no attacks manage to dent its arguments, it comes out even stronger).3
  • They perform proper power analysis so that their sample size is sufficient, and their subsequent statistical analysis is airtight.
  • They are overly conservative to exclude confounding explanations, and only measure a single moving part. Furthermore, they restrict their analysis to bugs that are immediately fixable by including types, and exclude anything that might require more advanced refactoring to accommodate typing. So in reality, the effect is plausibly a lot bigger, but certainly no smaller than what they reported.
  • And finally, they don’t find a slight effect but a staggering difference. Despite their overly conservative procedure, even at the low end of the 95% confidence interval they find that there are at least 10% of bugs that would simply vanish with minimal added type checks.

Unless there is a fundamental flaw in the paper that nobody has yet discovered, the paper conclusively shows a large benefit of static typing, at almost no cost.4


On a historical note, research on typing disciplines in programming has had a rocky start because, for a long time, the evidence wasn’t clear at all. The reason for this is that doing systematic experiments to examine the effect of static vs dynamic typing isn’t easy: a systematic experiment must isolate the effect we’re investigating. And unfortunately we can’t isolate the effect of the typing discipline, since it’s tied to the programming languages.

There actually were programming languages that allowed both static and dynamic typing in different dialects (e.g. VB with Option Strict On or Off, or statically typed Lisp). However, these weren’t well suited for a direct comparison, most importantly because there were no existing, sufficiently large code bases that allow direct comparison. At best we could compare them in “laboratory settings”, where test subjects randomly solve a task in the statically or dynamically typed variant of the language.

Unfortunately these artificial programming assignments don’t model real-world usage well. In particular, many of them are small in scope and solve a well-defined problem that can be summarised on half a page of text.

Luckily that’s in the past, because TypeScript, Flow and JavaScript are indeed the same languages except for static typing, and because there is an extensive real-world dataset of code and bugs to sample from.


1 Inspired by a quote from the original paper.

2 I am not entirely happy with this: one of the main strengths of statically typed languages is that ostensibly type-unrelated problems can be phrased in ways that can be statically type-checked. This transforms many logic errors into type errors, which drastically increases the rate of bugs that can be caught by static typing. In fact, the paper roughly classifies type-unrelated bugs and I contend that a large percentage of those could in fact be caught by static typing.

3 I invite anyone, especially proponents of dynamic typing, to try to find unaddressed flaws in the analysis. I don’t think there are many (if any), and I’m confident that no potential flaw would materially alter the outcome.

4 I suspect that the actual cost of static typing in real, large-scale projects is nonexistent, since it then becomes a natural part of the architecture and might even simplify planning. Fixing static type errors takes time, but much less than errors discovered later. This has been extensively empirically studied and has been known for decades (see e.g. Code Complete).

11
  • 4
    I know this is a late answer to this question but I believe that the new evidence (which I explain here) changes the complete static-vs-dynamic debate. May 22, 2018 at 18:49
  • 4
    It's certainly interesting, but I wonder how much it relates to javascript's particular typesystem. Python's (especially python3) type system is far stricter with a lot less implicit conversions. May 22, 2018 at 21:05
  • 1
    Haskell and Idris go much further with static typing than other languages where you can create your own "Actions" using Monads that can statically specify exactly how you can combine "statements" (which are modeled as functionally pure expressions that pass around their environment / locals around in their "hidden" layer). Despite the fact that Haskell can catch 30-80% of errors in its types, I don't see people talking about massive productivity using it.
    – aoeu256
    Jul 20, 2019 at 14:21
  • 5
    @LieRyan If anything that renders the analysis overly conservative, as noted in my description and elsewhere. It by no means invalidates the analysis. Your 1% estimate is, honestly, laughable. Itʼs completely off, your intuition is letting you down. Likewise, your characterisation of issues with static typing is typical of a practitioner of dynamic typing who had little actual experience with modern static typing (i.e. not just Java). Aug 3, 2019 at 12:34
  • 2
    @LieRyan "You just don't make type errors to begin with." Your comments are risible.
    – user76284
    Apr 4, 2023 at 1:36
12

Is type safety worth the hit to speed of development and flexibility?

So really this comes down to what you are doing. If you are programming say, the backup systems for airplanes, type safety is probably the way to go.

Dynamic language vs Static language programming are really two different animals. They both require a fundamentally different approach from each other. You can mostly port a method of approach between static and dynamic, but you'll lose out on the advantages of the other.

It's a mindset really. Is one better than the other? That really depends on who you are and how you think. Most of the people I work with would never touch a dynamic language if they didn't have to, because they feel there is too much room for error. Are they wrong to think this? No, of course not, but it does mean that they have realized that their approach of applying their coding style won't work in a dynamic environment. Other people I go to user groups with are the exact opposite. They find static typing too cumbersome, because it limits their approach to solving certain types of problems.

I can honestly say, I jump between JavaScript and C# a lot. Now, knowing and working in both languages does influence the other to some extent, but in truth, the code I write in each look entirely different from the other. They require a different approach, because they are fundamentally different. What I've found is that if you find yourself thinking, "Man this is so much harder to do this in X language," your approach is probably off a little. Here's an example, people talk about the "Pythonic" way of doing things. What it means is that there is a way the Python language works to make a problem easier. Doing it some other way is generally harder, and more cumbersome. You have to get over the hump of knowing how to a language works to really it work for you. It's the exact same thing with dynamic vs static languages.

1
  • I've been under the impression for a while that programming languages should only hide features of your code that you don't ever need to think about. This holds for getting machine code all the way up to something higher-level like Java because that lower level of implementation is something you basically never need to deal with. This isn't the case for object types. In my opinion dynamic-typing just makes programming harder because it introduces an entire class of errors that you have to catch yourself.
    – man guy
    May 14, 2019 at 2:37
7

There was a similar question just asked recently: Dynamic vs Statically typed languages for websites

To restate the core of my answer:

As systems grow bigger, statically typed languages ensure robustness at component level and thus flexibility at system level.

Yes, Java is strictly typed and yes, Java sucks (no offense. it's awful. great platform & ecosystem, but one of the worst languages ever (actually being used)).
But infering from that, that strict typing sucks is just a fallacy. It's like pointing at PHP and infering dynamic typing sucks (again, no offense. it's slowly improving, I give you that).

Personally, I do most of my development in haXe, which has a static type system. Not only is it signifficantly more expressive, than that of Java and does it require much less effort due to type inference, but it's also optional. Should it ever get in your way, you just bypass it.

Type safety is a feature (this is something many supposedly high level languages don't get right) to help you prevent shooting yourself in the foot.
And about any succesfull dynamically typed language would be simply better, if you had the option have your code type checked at will.
For example, I certainly enjoyed experimenting Ruby, but that was mostly because Ruby is fully object oriented, which is entirely orthogonal to the presence of a compile time type system.

I think the claim, that static type systems are obstrusive is merely based on lack of knowledge of good static type systems. There's a number of languages that do it right, haXe being one of them, and arguably not even the best in that regard.

Example haXe code:

class Car {
    public function new();
    public function wroom() trace('wroooooooom!')
}
class Duck {
    public function new();
    public function quack(at) trace('quackquack, ' + at + '!')
}

function letQuack(o) o.quack();
letQuack(new Car());
letQuack(new Duck());

This will produce a compile time error:

Car should be { quack : Void -> Unknown<0> }
Car has no field quack
For function argument 'o'
Duck should be { quack : Void -> Unknown<0> }
Invalid type for field quack :
to : String -> Void should be Void -> Unknown<0>
For function argument 'o'

You can't really claim I had to put a lot of effort into type safety.

Saying that you don't need type safety, because you have tests is even more idiotic. Writing tests is boring and repetitive. And I really don't want to write a test, just to find out, that an instance of Car won't quack and a Duck needs someone to quack at.

At the end of the day, you will find, no matter how much overhead type safety costed you, it is eventually ammortized (even in Java - although maybe not that soon).

1
5

For whatever reason, I don't make errors related to the type of an object that often anymore. In languages like C#, I am more likely to make errors related to runtime casts than I am likely to make a compiler-detectable type safety error, which, I grant, is usually caused by the occasional need to work around the staticness of a statically typed language. When I write ruby, the code tends to hint pretty strongly at the type of an object and the availability of a REPL means that I've already experimentally verified that the desired method/attributes exist, or I'll have a unit test that does basically the same thing, so I also rarely run into type safety problems in ruby.

But that's not to say statically typed systems can't be better than they are.

Within statically typed languages, the type system actually matters a lot as well. As an example, with something like the the Some monad in functional languages (type<Some> := yes x | no ), you gain compile-time checks that essentially prevent the dreaded NullReferenceException common in most type systems; when pattern matching code runs, you get compile time errors telling you that you failed to handle the null condition (if you use that mechanism to declare the type). You also reduce similar types of errors when you use things like the |> pipeline operator in F#.

In the Hindley–Milner tradition of static typing, you can build things that give you far more than a guarantee that a type claims to support interface X, and once you have those things, I'd say that the statically typed system becomes a lot more valuable.

When that's not an option, Design By Contract extensions to C# can add another set of mechanisms that increase the value of the static type system, but they still require more discipline than some of those functional paradigms.

5

It depends.

Human failure modes are often statistical. Strong type checking reduces the likelihood of a few certain types of human failures (causing buggy code). But just because you can fail doesn't always mean you will (Murphy non-withstanding).

Whether this reduction in potential failure odds is worth the cost depends.

If you are writing code for a nuclear power plant or ATC system, any human failure mode reduction might be extremely important. If you are rapid prototyping some website idea that has no spec and with near zero failure consequences, then the reduction in failure modes or probabilities may or may not buy you anything, but may cost you in development time (more keystrokes, etc.), and in brain cells distracted by memorizing the current type(s) required.

3
  • 3
    Your scenario of rapid prototyping is hinted to be wrong in Paul Hudak's paper about a US navy study which required to develop an AEGIS-like simulation in different languages, one of which was Haskell. It meets almost all your criteria: it was rapid prototyping, the requirements where ill-defined, and the cost of failure was near-zero (this being an extremely informal experiment). Haskell came out the winner in evey category: development time, exceeding the requirements, requiring fewer LOC, and producing the only working example among all contestants!
    – Andres F.
    Aug 6, 2015 at 19:35
  • 2
    The paper: Haskell vs ..., An Experiment in Software Prototyping Productivity - Paul Hudak and Mark P. Jones. It describes the results of an experiment ordered by ARPA and the US Navy.
    – Andres F.
    Aug 6, 2015 at 19:38
  • Wasn't the winner Relational Lisp? Man, I wish there were vids showing people coding things in Lisp with all of those weird powerful extensions like Shen (a logic-relational framework that allows you to give dependent types to code and mix-and-match type code with non-type code), super-CLOS frameworks with predicate dispatch, etc...
    – aoeu256
    Sep 28, 2019 at 0:15
4

Types are constraints on interfaces, so they're a subset of what you may want to test with unit tests, and so a lot of the trade-offs are similar:

  • Static types give earlier feedback on whether or not the code meets the requirements that can be expressed by the type system, in exchange for delaying feedback from building something minimally functional (like customer feedback or higher level tests).
  • Knowing that the code meets certain requirements can ease refactoring and debugging, but it also adds overhead to changing interfaces and changing requirements.
  • Particularly if a statically typed language lacks coercion, it provides added security against code being used on data that would cause bugs (reducing the need for conditionals and assertions), but overly restrictive constraints require the user to write more code to massage their data into an acceptable form (such as explicit type casting).
  • Explicit type annotations can aid understanding when reading code, or it can clutter code with redundant or unnecessary information.
  • Depending on implementation, it can detract from terseness. This depends on things like whether type annotations are required or inferred, how well the type system can express generic types/interfaces, the syntax, and whether or not you intended to test for constraints that can be expressed by the type system (i.e., the same test is likely more terse as a language feature than as a unit test, but you may not have intended to test it).
  • Additionally (but unrelated to TDD), static types can aid compile time optimization, at the expense of requiring that types check (and taking the time to check them and perform the optimizations), and better optimization can be done if data is restricted to types that map well to hardware. This eases development on code with performance requirements, but can cause trouble for code that doesn't fit these constraints well (as per point 3).

To summarize, I'd argue that dynamic languages are particularly useful for prototyping, whereas if you need to be sure that your code is correct, you should favor a strong type system.

3

You're not going to get a truly objective answer to that, but my experience is that type-safety is invaluable until you master TDD. Once you have heavy unit-test coverage, where the tests have been written before the code, the compiler-checking becomes a pain and actually starts getting in your way.

5
  • this is a subjective QA so I'm fine with that. Mar 18, 2011 at 18:21
  • 1
    Anyone care to explain the down-votes?
    – pdr
    Mar 18, 2011 at 18:26
  • Can't help you with the explanation but I gave you a +1, I think this is a useful contribution. One of the key fears with dynamic typing is that you'll make a change somewhere and break something somewhere else due to assumptions that would have been enforced by the compiler in a statically typed language. Heavy unit-test coverage will protect you here. Mar 18, 2011 at 20:54
  • 5
    I didn't downvote as you made a valid point, although no offence intended, but your post comes across as a little TDD fanboyish, which is probably why the downvotes. Mar 18, 2011 at 22:19
  • @Karl, No offence taken, it was a genuine question. I can be unapologetically pro-TDD, I admit
    – pdr
    Mar 18, 2011 at 22:40
3

There have been a lot of very complicated systems written in Lisp, and I haven't heard any Lisper complaining that they wanted static typing. When I worked with it, I don't remember any problems that slowed me down much that a static type system (and you can specify types statically in Common Lisp) would have caught.

Moreover, mainstream statically typed languages don't seem to be well suited for catching errors. In designing a layout, what's important is that a certain number is a vertical measurement on the page, not whether it's int, unsigned, float, or double. The compiler, on the other hand, will often flag type conversions it deems unsafe, and happily let me add a vertical measurement and the number of characters in a string. This weakness of the static type system was the original idea behind Simonyi's Hungarian notation, before it was bastardized into ugly uselessness.

1
  • LISP's macros are run at something close to "compile time", so any assertions inside the macros are almost the same as a type system, however, the macros can add many types of errors not possible in languages without macros haha. The insane expressivity of LISP can reduce the size of programs by allowing easy eDSLs, and these eDSLs can be specialized so that certain type of errors are not possible (just like in HTML there are few types of errors possible).
    – aoeu256
    Feb 26, 2021 at 13:23
3

Yes, definitely. One thing you'll find as you use both strongly typed languages and Python(Python is strongly typed) more is that most well-written code in dynamic languages tends to follow a lot of the same conventions as strongly-typed code anyway. Dynamic typing is very useful for serialization and deserialization, but for most other things it really doesn't contribute much of an advantage. And unless most of your code is serialization-related, why throw out the free error-checking?

1
  • 4
    Strongly-typed languages such as Java and C# handle deserialization automatically through the use of Reflection. Mar 18, 2011 at 18:31
3

Morgan, I got an interesting idea for you to try: static + dynamic typing. You mentioned Python, C# and Java. Were you aware that there are some pretty good ports of Python to both .NET and Java? In both cases, the ports let you use the libraries of those platforms and/or interoperate with existing code. This gives you several possibilities:

  1. Keep legacy code in static, inflexible language. Use Python for new stuff.
  2. Use Python to prototype new stuff on top of mature platforms. Re-code the components you want to keep in the more mature language.
  3. Use the dynamic language for portions you change often.
  4. Possibly use the dynamic language to play with ideas like modifying running code.
  5. Do everything in the dynamic language except for the critical parts where you use the strongly typed language.

I used these approaches as far back as the late 90's to get around the pain of developing in C/C++. I needed the native libraries and sometimes performance. Yet, I wanted the better syntax, flexibility, safety, etc. So, the trick was carefully combining them to get the right tradeoffs. It was often better in practice than throwing the whole language and legacy code out for another language/platform.

(Note: An answer already said it, but I also want to re-emphasize that dynamic typing != no/weak typing. Many dynamic type systems use strong typing on the inside. The way I think about what makes a type dynamics is that a variables type is determined at runtime, doesn't need a type annotation, and/or might change at runtime.

2

I see this question come up alot, and I think that your software quality (and lack of bugs) has more to do with your development process, how your system is architected, and the commitment of you and your peers to code quality.

My last job was mostly python development. I worked for a large, international web hosting company and we had dev teams in the US, Canada, and South Korea. Custom python web framework for front end customer app that allowed the users to manage their domain names and web hosting accounts. Backend: all python too. Python web service to talk to individual servers to do things like provision a new web hosting site, create a new blog, create dns entries in our name service system; etc, etc. In my current job, client apps our all in java; our main product is a mixture of java and flash. Custom java web framework for our older apps, wicket for our newer internal tools.

Having worked in both, I have to say this question bugs me every time I see it. If you are using a dynamically typed language and actually test your code you'll be fine. If the system is designed well, and you follow standards, you will be fine. There were never a lot of bugs that came up due to lack of a compiler checking types. Most bugs were logical errors, just like my java job today.

2

Is type safety worth the hit to speed of development and flexibilty? WHY?

Static typing is a net increase in the speed and flexibility of development throughout the software's lifecycle. It reduces the total effort and inconvenience, but moves a lot of the effort and inconvenience upfront, where it is more noticeable. The entry barrier to having working code is higher, but once you get past that barrier (by satisfying the type checker), extending and maintaining that code takes much less work.

There will always be some headaches in software development because of:

  • The inherent complexity of what you are trying to accomplish

  • The inherent fallibility of humans, especially considering that we make more mistakes when we try to do something more complex

Sooner or later, you need to take some time to address these challenges. There is no getting around that. Static typing simply addresses these challenges sooner rather than later. Sooner is better than later, because the later you discover a mistake (not a question of if, but when), the more it costs to correct that mistake.

It costs much less to correct a mistake reported by a type checker than it costs to debug a type-related exception raised at runtime. Deferring type-checking to runtime is just sweeping the problem under the rug.

1
  • There are some programs like the ones in data science, where you want a REPL/edit the program while its still running and if your working on a REPL, and there is no difference between run time and compile time deferring error checking to run time brings fewer benefits. I remember in Haskell there was a type extension that made all code dynamically typed for use in the REPL and it gave you easier to read type errors.
    – aoeu256
    Feb 26, 2021 at 13:30
0

YES.

I have worked in PHP applications, where types are not as "strong" as in Java or C#. Usually I finished "simulating types", because, in order to avoid bad automatic conversions, or validating data.

Dynamic Type Languages are good for O.S. scripts and quick small apps., not complex apps.

Summary: If I have to choose between an "Weak Type" or "Dynamic Type" Programming language, or a "Strong Type" Programming Language for a complex, business application, I choose the "Strong Type" Programming Language.

0

This is just my own opinion, but no, I don't think that type safety is worth it. Not even for a second.

I've been a developer for long time. Starting off with c++, c#, then moved to javascript (frontend and backend via node.js). Since I've been developing in javascript my productivity has sky-rocketed, to the point that I actually get aggravated using type-based languages. I'm also against compiling, I want everything to be in run-time now. Interpreted languages is really where I found my love for programming.

As far as types, I just don't see any benefits. I see types now the same way I see memory management. Completely unnecessary. The languages of tomorrow should completely shield the developer from knowing anything about types. The computer should understand types and leave the developer out of it.

Here's an example. I was just using Swift (Apple's new language) hoping it'd actually live up to its name a day ago and tried to do: var n = 1/2 didn't work. I was like, what's going on here. and then sadly realized I had to do var n: Float = 1/2. This reminded me how much I hate type systems and how much of an unnecessary aggravation they are.

I'd even go another mile to say that I don't even want user defined types (such as Classes). I don't want types at all. All I want is var and objects. Where any object can be used as any object. And objects are dynamic and constantly changing. Where it becomes a runtime issue as to what works and what doesn't.

Developers love to say how loosely typed languages aren't good for big projects. But I'd say it's the opposite. Strongly typed languages are horrendous for large projects. And if you say javascript doesn't work for big projects, ask Uber a 40billion+ company that runs all it's backend on node.js/javascript, or Facebook that started with PHP.

As far as statically typed languages it's not good for today's quick iterations. here's a simple example, you have 10 developers working on a .net project with a continuous integration server, one developer submits a mistake and the entire build is broken, even though the 10 developers are working on different things they are now all stopped and waiting for the offending developer to correct his mistake. Talk about efficient huh? Type system / static languages are interdependent in that way and make your code interdependent. However, script files are never interdependent. If there's a problem with one of the scripts it doesn't halt production, all the problems you'd see are left to the runtime. And the runtime never stops. It never breaks. It might produce wrong output but it doesn't just halt the entire process the way type systems do.

7
  • 1
    A lot of "I"s, not a lot of substance of argument. And by the way whether or not an error "breaks" the build has nothing to do with static vs. dynamic. If you have unit tests and one fails "your build is broken" and hopefully not deploying to production until that's corrected
    – nafg
    May 29, 2015 at 10:45
  • What made you think I implied any such thing?
    – nafg
    Jul 7, 2015 at 21:01
  • Your productivity in javascript did not skyrocket because javascript lacked types. You're productivity skyrocketed because C++ and C# are heavy languages. Javascript + types will actually make your productivity skyrocket even further. Nobody said javascript is impossible for large projects. Javascript on large projects is certainly do-able. However it is not ideal. Unit tests take the place of type checking, also unit tests have limited type coverage while type checking has 100% coverage.
    – Brian Yeh
    Jan 21, 2018 at 10:37
  • 1
    @BrianYeh c++ and c# are heavy languages because they're centered around types. I just started using reactjs at my job and my productivity has plummeted yet again due to it incessant use on types and components. if you like types and unit tests, good for you. not all of us share this programming style.
    – user19718
    Jan 22, 2018 at 18:42
  • 1
    @foreyez reactjs doesn't have types. You are probably referring to flow. Unit tests take the place of type checking so if you don't have type checking you need more unit tests. Unit tests and types are opposing forces. Your productivity going down is an illusion. Any type error you catch in a type safe language is an otherwise uncaught error in a dynamically typed language. It only appears faster. The type safe language forces you to deal with those errors up front.
    – Brian Yeh
    Jan 22, 2018 at 20:11
0

I think it pays to take a step back and consider when does dynamic typing cause problems.

One case is where a code branch is not tested at all, but frankly code that is never tested is likely to be buggy whether dynamic typing is in use or not.

Another more subtle problem though is imperfect substitutability.

If a type is just completely wrong then unless a particular code path is never used that is likely to be detected quickly.

On the other hand if a type is an imperfect substitute then the code may mostly work but break in subtle ways that won't be detected until much later.

Two of the most common types in programming are numbers and strings. In many dynamic langauges they are imperfect substitutes for each other. In say javascript or php if you provide a number where a string is expected or vice-versa your program runs without raising an error but can misbehave in rather subtule ways.

Python avoided that particular problem, numbers and strings are in no way substitutes for each other and trying to use one where the other is expected will normally lead to rapid failure.

However it did not avoid the imperfect susbstituibility problem completely. Different types of number can be imperfect substitutes for each other, so can different types of sequences.


What I am getting here is I don't think it's possible to compare the benefits and costs of static and dynamic typing in a generic way, because I think both the benefits and the costs depend on the particular variation of static or dynamic typing a language uses.

Not the answer you're looking for? Browse other questions tagged or ask your own question.