For four days, I spent debugging a python production script because in one place I had typo'd ".recived=true" on an object and just couldn't understand why my state machine wouldn't work.
And very quickly, the whole team became fans of __slots__ in Python.
I still write 90% of my useful code in python, but that one week of debugging was exhausting & basically wouldn't have even compiled in a statically declared language. Even in python, the error is at runtime, after I got the __slots__ in place.
Is that really a dynamic typing problem or a language that allows you to create instance members anywhere? It seems like that is a flaw in the declaration model of the language and not a static / dynamic issue.
$ txr
This is the TXR Lisp interactive listener of TXR 185.
Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
1> (set a.b 3)
** warning: (expr-1:1) qref: symbol b isn't the name of a struct slot
** warning: (expr-1:1) unbound variable a
** (expr-1:1) unbound variable a
** during evaluation of form (slotset a 'b 3)
** ... an expansion of (set a.b 3)
** which is located at expr-1:1
Both warnings are static. If we put that into a function body and put that function into a file, and then load the file, we get the warnings.The diagnostics after the warnings are then from evaluation.
Those are nothing; TXR Lisp will get better diagnostics over time. I'm just starting the background work for a compiler.
There is dynamic and then there is crap dynamic.
Don't confuse the two.
There is crap static too. Shall we use C as the strawman examples of static? Hey look, two argument function called with three arguments; and there's a buffer overrun ...
I mean, we can argue the semantics of what, exactly "static type checker" means, but...
A "static language" occurs when we have a model of program execution that involves erasing all of the type info before run-time. Or most of it. (Some static languages support OOP, and so stuff some minimal type info into objects for dispatch.)
Note how above, my expression executes anyway; the checks produce only warnings. The warning for the lack of a binding for the a variable is confirmed upon execution; the non-existence of the slot isn't since evaluation doesn't get that far.
If we retain the type info, we have dynamic typing. There is no limit to how much checking we can do in a dynamic setting. The checking can be incomplete, and it can be placed in an advisory role: we are informed about interesting facts that we can act on if we want, yet we can run the program anyway as-is.
Excellent. My point exactly. I have no fear of using a static or dynamic language, as long as it is a good implementation of a statically (or dynamically) typed language.
nothing stops you from using static typing with python3
The typing spec provides for supplementary "stub files" that can be provided for third-party dependencies without their own annotations. The typeshed project provides these for a fair and quickly increasing number of common dependencies, and is plugged into pycharm and mypy by default: https://github.com/python/typeshed
Can we stop pretending that adding type annotations to a 'dynamic' language solves the "good static typing" problem? It's just silly.
(About as silly as pretending that static types solve all problems.)