Optional typing like the one we see here is not uncommon in other dynamic languages: For instance, Clojure has core.typed and prismatic schema, which approach the problem in ways related to what the article shows.<p>However, while optional typing gives you some benefits over purely dynamic typing, the fact that it's all bolted-on causes a variety of problems. First, there's the fact that you'll have code with types interact with code without them. This eventually causes more trouble than it solves.<p>IMO, the biggest issue though is that what we really see from most of these systems is to add optional type systems that are comparable to very simple type systems, like Java's. But those strongly typed systems are not really that powerful! The real power of static typing doesn't come from being able to make sure we don't mix strings and integers, but in doing type checking for much more complex abstractions. Type systems like Scala's, or Haskell's. Creating an optional typing linter that looks at that high a level, and doesn't cause much of pain, is not something I've ever seen. Type inference with generics, existential types, higher kinded types, algebraic types. That's where the real value is, and where modern typed languages are.<p>Aiming optional typing at where typed languages were 20 years ago is not going to help bridge the gap. If anything, I think it makes it wider, because then fans of dynamic languages think they understand the position of proponents of type systems when, in fact, they are looking at a strawman from the past.
The main advantage of static typing to me is that it enables automatic refactorings.<p>Without types, it's impossible for tools to refactor your code safely without the supervision of a human. This leads to developers being afraid of refactoring and, ultimately, code bases rot and become huge piles of spaghetti that nobody wants to touch.<p>With a statically typed language, I'm never afraid to refactor whenever I see an opportunity to do so.
The SBCL Common Lisp compiler detects some of those type errors at compile time - especially for declared types:<p><pre><code> ; (> SECRET GUESS)
;
; caught WARNING:
; Derived type of GUESS is
; (VALUES STRING &OPTIONAL),
; conflicting with its asserted type
; REAL.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
; printed 8 notes
</code></pre>
Common Lisp allows optional type declarations. SBCL (this feature it has inherited from CMUCL) uses those as compile time type assertions.
The Python PEP 0484 approach, unchecked type hints, is strange, and probably a bad idea. There are good arguments for entirely dynamic typing, or entirely static typing, or optional static typing. Those have all been used successfully in other languages. But optional static typing <i>without checking</i> is new. (It may have been tried in some forgotten language, but it never made it into a mainstream one.)
This is likely to create bugs, rather than fix them. The type you see looking at the code may not be the type being used there. This will confuse maintenance programmers. Worse, the compiler itself can't rely on the type info for optimization purposes. This limits optimizations in PyPy. Type checking is supposed to be performed by third party programs.<p>The syntax is backwards compatible, and this doesn't fit the language well. Forward references to types are handled via a really tacky kludge: "When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later." So, sometimes you write<p><pre><code> def foo(item: 'Tree'):
</code></pre>
instead of<p><pre><code> def foo(item: Tree):
</code></pre>
It's not stated in what scope 'Tree' is evaluated. So don't reuse type names.<p>Some type info is in comments:<p><pre><code> with frobnicate() as foo: # type: int
# Here foo is an int
</code></pre>
Also, Python is getting header files (called "stub" files), like C. In most modern languages, such as Go and Rust, that's all handled automatically by storing type info in the object files. But in future Python, that will be manual.<p>There's function overloading, sort of. There's "@overload", but it doesn't really do anything at run time yet.<p>This whole thing is a collection of hacks in search of an architecture. This is the messiest type system of any mainstream language. Well designed type systems are hard enough. This is not one of them.<p>If this hadn't come from Python's little tin god, it would have been laughed out of the Python community. Stop him before he kills again.
> Probably this will still not be enough for Python enemies though.<p>Because it doesn't appear to actually do anything. It's a joke to call this 'static typing'.
What does mypy do if you make a call from code with type annotations into code without? Or vice-versa?<p>Has anyone ever gotten paid to add annotations to code that works?<p>Personally, I view type systems as like a safety line when doing work on a roof, and optional typing as having a line that might or might not be tied off.
Having type annotations that are ignored at runtime would cause problems when you interact with code without type annotations, no?<p>PHP has a (unfortunately quite limited) set of type annotations, but the interpreter actually enforces them.
Here's a longer article (<a href="http://codon.com/consider-static-typing" rel="nofollow">http://codon.com/consider-static-typing</a>) with more background / history about static typing and Ruby.<p>This topic has been knocked around in Ruby-land for a while; I remember seeing Michael Edgar's LASER (<a href="https://github.com/michaeledgar/laser" rel="nofollow">https://github.com/michaeledgar/laser</a>) static analysis tool including some work around optional type annotations, but seems like development there has stopped.
Aren't type annotations in python just documentation that's designed to look like it's not? Seems like it would make more sense to just create a documentation standard than develop a brand new syntax for documentation. Another idea that makes more sense to me is to use @decorators. I really don't understand why this syntactic hack is supposed to be a good idea.
Has anyone ever tried to implement optional typing in python with just generators?<p>It seems like a generator like @Signature(...input types, output type) would solve this problem with limited language changes, and would work in python 2/3?
Since I unit-test the heck out of my code, this doesn't really do much for me. Unit-tests test actual values (which is where the interesting bugs come from IMO) and give me more powerful refactoring capabilities than an IDE.<p>The real benefit I'd be looking for is the chance to give the compiler hints to speed up execution times.
Ugh. I have hardly any type problems in my Ruby code. I've gotten very good at recognizing implicit state and capturing it in a properly instantiated object with a well-named class. I daresay that if you don't have this skill, a type system isn't going to help you much and you're going to get nasty bugs anyway.<p>The problem in Ruby is nils, and you'd have the same problem with the same solution in a static language; creation of a duck type. You can't get away from duck types, whether it's a maybe type or whether you perform nil-checking at the earliest possible opportunity. You learn with time and experience how to deal with inconsistent data. Ruby gives me the flexibility to do it without a lot of boilerplate.