A lot of people seem to believe that dynamically typed languages make development easier, because you don't have to worry about writing type annotations or going through the extra steps to fix compile-time errors.
This is arguably true for small scripts, but for anything non-trivial I find that static typing means I can be more productive, because type errors are caught straight away (rather than potentially in production), and I can be much more confident in refactoring code because I know certain kinds of errors will be caught by during type checking. This doesn't remove the need for automated testing, but does reduce the number of test cases you have to write.
Things have improved a lot in the Python ecosystem of late with the introduction of type annotations and mypy, so to the extent possible I treat Python as if it's a statically typed language, putting type annotations everywhere and always making sure the codebase passes type checking before pushing a commit.
However, the fact that this is optional sadly means that not everyone does it, and if you're working with parts of a codebase written without this level of discipline, you're basically back to square one. I've come to the conclusion that for medium to large projects, dynamic typing encourages sloppy programming, because it doesn't force people to think as carefully about what exactly their data types are, and whether they're being used correctly.
I hate that some universities teach dynamically typed languages as first language in their curriculum. I think for CS students the first language should be as "strict" (not in the mathematical sense) as possible, so the student is forced to think very carefully what is going where. This is of course a controversial opinion, especially among proponents of SICP (which is, in my opinion, not a good book for beginners. Yes, downvote me).
(Obviously, I am talking about CS students here, not about the general public who just want to learn what writing a program means)
I think Go would make a pretty good language for beginners, but I haven't tested that theory. TypeScript might be the safer bet, especially since you can run it in the browser and see things, which is probably somewhat more gratifying than printing text to a console.
I would go on a limb and say Rust (or more specifically, a limited dialect of it) could become a good language for beginners if:
- the compiler had better life time inference, so that you wouldn't need to annotate simple functions and introduce beginners to complex issues related to lifetimes, i.e it should "seem" to work like python, initially.
- better learning resources for absolute beginners are developed, step by step tutorial, an easy to install full IDE with friendly error messages etc.
I feel the same. Java and C# have an equivalent called 'var'. Unless the scope is tiny, I always avoid it. Also, in Java when you create a lambda, it is possible to exclude the parameter types.
foo(x) -> get_something_complicated(bar(x))
It is not good for readability in large source bases.
and you can decide whether you want a value (no &'s), an lvalue reference (&), or a forwarding reference (&&). I think with C++20 you can also use a concept instead of auto for a constrained parameter type.
The thing I like about Python is that I can decide, even on a line-by-line basis, but more likely on a program by program basis, if it makes sense to be type oblivious, or type checked.
> I can be much more confident in refactoring code because I know certain kinds of errors will be caught by during type checking.
I'll add to that: static typing also guarantees that your annotations are correct and complete. Prior to Mypy, in the Python world, we would document types in docstrings, which meant that docstrings gradually came to be incorrect--a function that returns a string might sometimes return `None`, but you called it assuming it always returned a string. In other cases, people (including the Python maintainers via the stdlib) will add annotations like "argument 'foo' is a file-like object", which is ... insufficient (do I just need a "read()" method? or do I need to implement "seek()" and "close()" as well?). Ultimately, in the absence of static analysis, a lot of time is wasted reading source code trying to understand the actual type signatures.
> Things have improved a lot in the Python ecosystem of late with the introduction of type annotations and mypy, so to the extent possible I treat Python as if it's a statically typed language, putting type annotations everywhere and always making sure the codebase passes type checking before pushing a commit.
This hasn't been true in my experience. Last I checked, Mypy still couldn't express things like recursive types (think "JSON" or "recursive linked list"), and a lot of things still required jumping through obscure hoops (defining a callback with kwargs). I also couldn't figure out how to export type annotations in my packages, and I had a lot of trouble getting mypy to pull in type stubs for packages that didn't provide their own annotations. In general, Python's typing story still feels very shoe-horned, although it's been a minute since I last fumbled with it, so maybe some of this has improved.
> for anything non-trivial I find that static typing means I can be more productive, because type errors are caught straight away (rather than potentially in production), and I can be much more confident in refactoring code because I know certain kinds of errors will be caught by during type checking.
Fully agreed. It's not quite the same as Rust vs. Python, but I've pulled off several sweeping refactors and rewrites in Swift codebases that I wouldn't dream of even attempting with Objective-C.
This is arguably true for small scripts, but for anything non-trivial I find that static typing means I can be more productive, because type errors are caught straight away (rather than potentially in production), and I can be much more confident in refactoring code because I know certain kinds of errors will be caught by during type checking. This doesn't remove the need for automated testing, but does reduce the number of test cases you have to write.
Things have improved a lot in the Python ecosystem of late with the introduction of type annotations and mypy, so to the extent possible I treat Python as if it's a statically typed language, putting type annotations everywhere and always making sure the codebase passes type checking before pushing a commit.
However, the fact that this is optional sadly means that not everyone does it, and if you're working with parts of a codebase written without this level of discipline, you're basically back to square one. I've come to the conclusion that for medium to large projects, dynamic typing encourages sloppy programming, because it doesn't force people to think as carefully about what exactly their data types are, and whether they're being used correctly.