11 ms·
Revenge of the Types
- deleted 12y ago[deleted]
- notduncansmith 12y agoCould you expand on why you feel that way?
- pixelmonkey 12y agoSome people may not understand the context of this part: So not long ago someone apparently convinced someone else at a conference that static typing is awesome and should be a language feature. I'm not exactly sure how that discussion went but the end result was that mypy's type module in combination with Python 3's annotation syntax were declared to be the gold standard of typing in Python. Ronacher is referring to the fact that Guido van Rossum, the Python language creator and BDFL, recently said he wanted to make mypy's type annotation standard into a standard by making use of Python 3 function annotations. The original function annotations standard is PEP-3107[1], GvR's proposal is on the python-ideas list[2], and information on mypy can be found at the project's site[3]. I agree with Ronacher's conclusion; I don't think static types -- even if only used at runtime -- are a good fit for the language. As for function annotation syntax, I think we just need to admit that isn't really good for anything. Great article! [1]: http://legacy.python.org/dev/peps/pep-3107/ http://legacy.python.org/dev/peps/pep-3107/ [2]: https://mail.python.org/pipermail/python-ideas/2014-August/028618.html https://mail.python.org/pipermail/python-ideas/2014-August/0... [3]: http://www.mypy-lang.org/ http://www.mypy-lang.org/
- keypusher 12y agoThe thing that function annotation syntax is good for is the ability to catch errors before they hit your production server at 2AM on a Tuesday. If you can describe the types that a function accepts and returns, violations of those rules can be caught by static analysis such as pylint and let you know before you commit. The current approach in Python after refactoring a large chunk of code is to grep through all the existing callers, fix what you can find, run the tests and hope for the best.
- arthurdenture 12y agoThe argument seems to be that if the added type system is not perfect, then it will be useless. For a working counterexample, see the Closure Compiler (https://github.com/google/closure-compiler https://github.com/google/closure-compiler), which adds a bolt-on, underspecified, occasionally-changing type system to Javascript. Similarly to GvR's proposal (https://mail.python.org/pipermail/python-ideas/2014-August/028618.html https://mail.python.org/pipermail/python-ideas/2014-August/0...), the types are only ever checked at compile time: there's no attempt to use them as runtime assertions and very limited attempts to use them for compile-time improvements. So, yes, because they are imperfect and optional, you don't catch every type error, and you need to add type hints / casts that in a perfect system wouldn't be necessary. Is this kind of flawed type system worth it? Hell yes. I've maintained large programs in both Python and (closure-compiled) Javascript, and with the former I've wished I had the help of the limited type checking available in the latter.
- mmagin 12y agoI didn't know Python users hate static typing so much.
- eliben 12y ago"Python users" is a vast generalization (this is literally one of the most popular programming languages in the world - there are a lot of users), and "hate" is a strong word. So if you want to convey meaning in your comment, you should try to be less hyperbolic. FWIW: I'd argue that most "users" of Python don't know the difference between static and dynamic typing. Or care about fanatic language wars in which the word "hate" is used to describe preferences between purely technical details.
- ayrx 12y agoI don't "hate" static typing. I dislike the current proposal though, because the proposed syntax is a horrible wart on top of a very elegant language.
- johnmaguire2013 12y agoDo you mean aesthetically or the proposed specifications?
- ayrx 12y agoLittle bit of both actually. If the primary motivation behind optional type checking is IDE hinting and compile time checks I'd actually prefer a standard docstring format instead of annotations.
- pjungwir 12y agoRandom question for the type experts out there: is there any language that lets me track the units of my numeric variables? For instance, something like this: float<km> drop(float<m> x0, float<s> duration) { float<m> x = x0; float<s> t = 0; float<m/s> v = 0; float<m/s^2> g = -10; float<s> dt = 0.01; while (t < duration) { v += g*dt; x += v*dt; t += dt; } return x * (1<km>/1000<m>); // abbrev for a cast: (float<km/m>).001 } Then I want the compiler to check that I'm not mixing up my units. It seems like this would be really useful, but I've never seen it before.
- sfk 12y agoFrom what I've read, Ada can do this.
- the_mitsuhiko 12y agoIn theory you can do that in any language that allows you to override operators. It's definitely being done in Rust. For instance you sleep for `Duration::milliseconds(10)`.
- bjz_ 12y agoStatically checked dimensional analysis is a great deal trickier though.
- thelinked 12y agoCheck out F#'s units of measure. http://msdn.microsoft.com/en-us/library/dd233243.aspx http://msdn.microsoft.com/en-us/library/dd233243.aspx
- hoggle 12y agoI've got to confess that I love how the design of MS languages regularly exposes my ignorance towards them. Edit: removed unrelated Wikipedia article (Unit Type)
- 12y ago
- bjourne 12y agoArmin didn't address what I belive is the main point of adding type annotations to Python: compiler checkable documentation and as hints to IDE:s. Seen in that perspective, a sucky type system is good enough because it's use isn't to verify program correctness. Personally, I think a standardized format for describing types in docstrings would be 100x better but that's not the way the Python core devs have choosen. Another argument in favor of types is that it will enable Python to optimize code better. But since Python isn't built for static typing, the CPython bytecode interpreter has no facilities for exploiting the extra information. And even if it had, the V8 Javascript VM proves that you dont need static types to generate optimized code.
- seanmcdirmid 12y agoYes. If you believe the point of a type system is to enforce correctness, then this doesn't make sense. Most type theorists seem to take this position. But if you believe that the point of a type system is to provide programmers with better feedback, then this completely makes sense. I wish more type systems research would explore on the latter rather than fixating on the former. Typescript and Dart have been developed with similar philosophies.
- slacka 12y agoI think Armin didn't address these valid points, because as he points out, "The first one is that I barely understand them[type systems] at all myself."
- keypusher 12y agoSeems odd for someone who doesn't understand type systems to be writing a high profile blog post about why they don't belong in Python, no?
- illumen 12y agoPeople should be able to write on their blogs their thoughts. It's a really good way to learn, and to get feedback on your ideas. Hopefully Armin listens to people who have been thinking about this for a long time, and done work in this area. But why should his ideas, which are admittedly uniformed, get spread wider than better ideas? This happens a lot anyway. I don't think it's entirely positive when people rant when they don't have the knowledge to back it up. However, it can produce a reaction from other people to step up and argue their case better. Or even better, to put out their code. I think in this case Armin does have a bit of a clue, and this essay is informing himself, and others quite well. You can statically check python with types now (pycharm pysonar2 etc), and you can use things like ABCs and interfaces to enforce constraints. "Union types" and "intersection types" are the type systems people have used to statically type check python, and other dynamically typed languages. You can see the various types coming into or out of a function. This is what Armin is talking about with Option/Composite types. So these various type systems which have been used to add extra type checking on top of python are now being blessed, and brought into the language proper. There are plenty of places in Python where the types are not specified well, because mostly it doesn't matter to people using it. Since the type checking tools have added external type definitions, and fixed up inconsistencies outside of the python implementations. So Armin is pointing out a few examples of type inconsistencies within python. There are lots more. Especially at the C API level, where things are a bit weird. But they haven't really bothered people that much, so they haven't been fixed. As someone who has written C extensions for python, I can tell you that it is weird, and things have changed with every python release (even, and especially in the 2.x series). However, these external type definitions are being brought together into the language (as per Guidos email) in the mypy format. There is a hope that the other definitions from tools like PyCharm can be translated automatically. These definitions are being used in useful tools today. These external type definitions are in effect a specification of the types for the core language, the standard library, and even other popular libraries (like Django etc). What came first the Duck or the specification of the Duck?
- Jweb_Guru 12y agoHrm. I think this article does a great job of explaining weird inconsistencies in Python's current type system, but I think it does a somewhat less good job of demonstrating that adding annotations is actively harmful. What would be some examples of situations where inconsistencies in the type system made annotations problematic in practice? Are those situations compelling enough to warrant not adding any annotations to the language?
- ivoras 12y agoNot only that, but look at the niche Python is occupying. It's a well established and respected niche to which, by definition, the language is suited very well. By adding static types, the focus of the language would move to a different niche, which would probably be already occupied by some competitor language(s) which do(es) types much better. If you want sort-of Python-ish syntax with elaborate types, just use Nimrod and leave Python alone. Get the right tool for the job, don't mutilate a perfectly good existing tool.
- hyperpape 12y agoWhat exact niche is that? Unless you mean "dynamically typed" (in which case that begs the question), I don't know what niche you think it couldn't occupy with static types. Not even arguing for static types: your comment is just really unclear.
- johnmaguire2013 12y agoAnd this argument would be why PHP is in the shape it is today.
- tosh 12y agoIf you want to learn more about how 'optional' and 'unsound' type systems can still deliver a lot of value there are some interesting articles on Dart's optional types: * http://journal.stuffwithstuff.com/2011/10/21/wrapping-my-head-around-optional-typing/ http://journal.stuffwithstuff.com/2011/10/21/wrapping-my-hea... * https://www.dartlang.org/articles/why-dart-types/ https://www.dartlang.org/articles/why-dart-types/ * https://www.dartlang.org/articles/optional-types/ https://www.dartlang.org/articles/optional-types/
- deleted 12y ago[deleted]
- jimmaswell 12y ago>So what's the solution? Not having null references and having explicitly typed arrays. Throwing the baby out with the bath water. Null types are extremely useful. I don't get why the author claims the null type in C# is a form of "damage". It's just said that it's bad, not why. The problem with None in python was that you can't tell what it's supposed to be. In C# you know what type the null is meant to be.
- the_af 12y agoWhat are nulls extremely useful for in programming languages? At least one serious problem with nulls in many languages is that you can get one somewhere you are not expecting it, and you won't handle it correctly, resulting in an null pointer exception (if you're lucky) or a crash (if you're unlucky). That's why alternatives like Option types are so useful: you really cannot ignore them, so they won't catch you by surprise. And at the same time, you can often handle them in pretty painless ways.
- aidenn0 12y agoIf you have ever programmed in a language with strict enforcement of something like a "maybe" or "option" type then you'll see that it's fairly trivial to have a separate type for a nullable pointer and a non-nullable pointer. It is essentially brain-dead that the type Foo really means "Either a Foo, or null" Failure to properly check for null is a source of many, many bugs, and there is an almost trivial way (assuming you're creating a new language, like C# was) to completely prevent it in statically typed languages that was well known when C# was invented.
- rurban 12y agoI don't see the issue. Armin went completely insane IMHO. This problem is usually solved by expressing the type "Foo or Null" as Foo? in such a gradually typed language. Maybe the critics should lookup the basic type literature first. Such posts will kill python. And this type of type critic already did kill python for Google. (And kept perl 10 years behind)
- 12y ago
- fish2000 12y agoPython's API structure may be fast and loose, but that is a feature, I think. Its type system may have some threadbare implementation spots – the _sre example from the standard library, for instance – but there are some compelling examples as well. I, for one, have been working on an app implemented mostly with PyObjC, the bridge between Python and Objective-C. I had all but written off PyObjC as a bizarre yet unuseful language mule... but lately I had the occasion to read through the PyObjC source code base, in service of my project. Did you know that when you subclass a wrapped Objective-C type in Python, an all-new Objective-C class is created and wrapped as the descendant class, behind the scenes? That blew my mind. That happens transparently, in concordance with Python's type heiarchy and runtime ABI. As it turns out, PyObjC predates Mac OS X, and the authors have put a lot of work into mitigating things like the GIL and system events. I am also a fan of Django's field type system, as the author mentioned – and I am curious about what he thinks about descriptors (which he mentioned one but did not address) – I think descriptors are an amazing addition to the duck-typing regime in Pythonville.
- gordaco 12y ago"Because there is basically no type system that fights against you, you are unrestricted in what you can do, which allows you to implement very nice APIs." If you feel like the type system fights against you, chances are that you are doing something wrong. When I program, the type system definitely fights for me. It gives me a lot of guarantees, plus it's a really convenient way of self-documentation. I mean, I'm not even talking about Haskell or something really sophisticated: I see the advantages even in old plain Java or C++ (so much that, in fact, most of my gripes about Java are about its type system not being complex enough). Also, being "unrestricted" is far from being an universally good thing, since it also means many more opportunities for mistakes. I know for a fact that I make more mistakes in languages without static typing, but well, I guess it's just me.
- eric_bullington 12y ago>If you feel like the type system fights against you, chances are that you are doing something wrong. Like most things, I think this depends on context. Doing exploratory data analysis in a static, strongly-typed language, for example, is extremely painful. And writing quick, one-time scripts in such languages is usually more trouble than it's worth. For this reason, Python is a wonderful language for doing data analysis and writing quick one-time data munging scripts (and yes, I realize that Python can be considered strongly-typed). On the other hand, I've now been exposed to languages like OCaml and Rust, and have had time to think about Java, and I now have a different attitude when I'm building a large application that will have to be maintained. I'm beginning to feel extremely vulnerable when I use a language like Python or (worse yet) Javascript to build such applications. It's not that I'm not a Javascript hater. I like Javascript in general -- it has a kind of functional feel to it, it's easy to prototype quickly, you can use it client and server, nice ecosystem, and unlike so many I actually enjoy async programming. And I've long enjoyed Python for similar reasons. But for building a robust application that will have to be maintained a long-time, you have to religiously write tests in these languages or you'll be buried in bugs. And even then, you still may be buried in bugs that a static, strongly-typed language would have detected. For this reason, I'm looking hard for an static, strongly-typed alternative to Javascript for the browser (i.e., a language compiling to JS) for building large applications. And Ocaml's js_of_ocaml is definitely on my list of things to evaluate. So the programming language philosophy that I adhere to now is encapsulated in the hackneyed old saying "use the right tool for the job".
- aikah 12y agoWe live in that wonderfull time in development,where a lot of things are questioned.A lot of languages that used to rule everywhere are questioned,like the OP,and devs try to come up with the ultimate language that would solve every use case. There is,of course, no such a language but future languages wether they are dynamic or static ,strong or weak (type wise) will certainly not make the same mistake as their ancestors. Personally I want a scripting language,with type inference but real strong static typing, that can be easily interfaced with C++, that handles concurrency the right way(ie not like javascript callbacks),that is trully multipurpose(like python) elegant(a bit like ruby), 00 with composition and strong encapsulation in mind and access modifiers, with immutable structures and variables by default but not limited to it,with some functional features without looking like Haskell,resonably fast for GUI dev,scientif computation and non trivial web apps,easy to deploy on a server, with sane error handling,IO streams everywhere, a clear syntax(no unreachable characters on non english keyboards everywhere),with a good package manager, an interactive repl(like IPython or the tool for swift,I forgot the name) and with battery included. So we are definetly living in an exciting period.
- ZenoArrow 12y agoHaxe (pronounced "hex") is pretty close to what you want... http://haxe.org/ http://haxe.org/ http://en.m.wikipedia.org/wiki/Haxe http://en.m.wikipedia.org/wiki/Haxe
- 1_player 12y agoI don't think C++ interface is easily feasible, as far as I know no language managed to do that yet, probably because of the wildly different ABI between C++ compilers. Anyway, I would add to your list Go concurrency constructs (channels, "go"-like statements), polymorphic types, and, personally, significant whitespace for indentation, like Python. Rust is a big step in the right direction, although it's a bit too complex|heavy for scripts.
- eru 12y agoYou probably also want sum types (or generally Algebraic Data Types) with your unicorn language.
- 12y ago
- Cyther606 12y agoI've been using Nimrod to replace Python on a Bitcoin project. elliptic.nim: https://github.com/def-/bigints/blob/master/examples/elliptic.nim https://github.com/def-/bigints/blob/master/examples/ellipti... elliptic.py: https://github.com/wobine/blackboard101/blob/master/EllipticCurvesPart4-PrivateKeyToPublicKey.py https://github.com/wobine/blackboard101/blob/master/Elliptic... Nimrod looks and feels like python, but it compiles to C. It's like C except with Pythonic syntax and with Boehm GC optional. In addition, Nimrod has a burgeoning NPM-like module ecosystem developing, albeit in the early stages. import rdstdin, strutils let time24 = readLineFromStdin("Enter a 24-hour time: ").split(':').map(parseInt) hours24 = time24[0] minutes24 = time24[1] flights: array[8, tuple[since: int, depart: string, arrive: string]] = [(480, "8:00 a.m.", "10:16 a.m."), (583, "9:43 a.m.", "11:52 a.m."), (679, "11:19 a.m.", "1:31 p.m."), (767, "12:47 p.m.", "3:00 p.m."), (840, "2:00 p.m.", "4:08 p.m."), (945, "3:45 p.m.", "5:55 p.m."), (1140, "7:00 p.m.", "9:20 p.m."), (1305, "9:45 p.m.", "11:58 p.m.")] proc minutesSinceMidnight(hours: int = hours24, minutes: int = minutes24): int = hours * 60 + minutes proc cmpFlights(m = minutesSinceMidnight()): seq[int] = result = newSeq[int](flights.len) for i in 0 .. <flights.len: result[i] = abs(m - flights[i].since) proc getClosest(): int = for k,v in cmpFlights(): if v == cmpFlights().min: return k echo "Closest departure time is ", flights[getClosest()].depart, ", arriving at ", flights[getClosest()].arrive
- progman 12y agoNice features: http://ivoras.sharanet.org/blog/tree/2013/Oct-2013-10-05.what-i-like-about-the-nimrod-programming-language.html http://ivoras.sharanet.org/blog/tree/2013/Oct-2013-10-05.wha... Type inference: http://nimrod-by-example.github.io/variables/type_casting_inference/ http://nimrod-by-example.github.io/variables/type_casting_in... Quick introduction for C programmers: https://github.com/Araq/Nimrod/wiki/Nimrod-for-C-programmers https://github.com/Araq/Nimrod/wiki/Nimrod-for-C-programmers
- ak217 12y agoOf all Armin's articles to date, this one I agree the most with. > Python is a language that suffers from not having a language specification ... There are so many quirks and odd little behaviors that the only thing a language specification would ever produce, is a textual description of the CPython interpreter... Keeping a language lean and well defined seems to be very much worth the troubles. Future language designers definitely should not make the mistake that PHP, Python and Ruby did, where the language's behavior ends up being "whatever the interpreter does". This is an incredibly important point. The rise of PyPy is just one compelling illustration of how Python is at a point where a language specification is needed, and these crazy CPython-specific bugs need to be purged. > I think for Python this is very unlikely to ever change at this point, because the time and work required to clean up language and interpreter outweighs the benefits. I would disagree - I think it's possible for Python to change this. Any such bizarre behaviors need to be treated as a bug, and eliminated in the next release.
- rdtsc 12y ago> Any such bizarre behaviors need to be treated as a bug, and eliminated in the next release. Going back in time (sorry for the long story). From what I observed, there seems to have been a split in the community. The split is between the importance for PyPy and its future vs the "core" CPython. When PyPy was making very fast progress there was a feeling that maybe in the next big release PyPy will merge into CPython. So maybe if you downloaded python 3.0 you'd just get PyPy with it. There was a lot of hype and hope. And I think at some level the old guard (Guido and some other core developers) saw that as bit of threat and they made public remarks that I understood to mean: "CPython is not PyPy", "it won't be merged in any time soon", "CPython is fast enough". So why all this background? Well that might explain why there would be resistance to modifying CPython to "help out" PyPy.
- TD-Linux 12y agoI think Python had one chance to do what you suggest - remove bizarre behaviors. This chance was Python 3. This is also one of the things that bothers me a bit about Rust. The complexity of the compiler means that writing an actual language spec is hard, and the spec is very much tied to "what rustc's borrow checker is capable of".
- sjy 12y agoIf the author is reading this thread, I spotted this type-o: Type type claims that it's a subclass of object.
- deleted 12y ago[deleted]
- wirrbel 12y agoThis is a very nice article showing some of the issues troubling python and the proposed type anotations. I would summarize my view of the type annotation proposal as follows: Statically typed languages can introduce inference heuristics that minimize the amount of type declarations. They can "jump" into the dynamically typed world more easily. The other way around is a lot harder. Not only are all those type annotations lacking in the standard library and the tools around, but there is also a lack of function design by types.
- rurban 12y agoNo, it's a horrible article. And no, they cannot. I implemented such a type inferencer for perl (B::CC), which has the exact same problem. With a highly dynamic run-time which changes the types at will, the compiler will never be able to do proper optimizations without explicitly forbidding certain coercions. The inferencer has to give up in 90% of all cases. Only with optional explicit types, esp. for loop counters and array members, those operations can be efficiently optimized. Up to 2000% for the typical array or loop benchmarks. And no, a v8-style tracing jit also does not help in all cases. This kind of run-time type caching has a huge overhead, and will always need an explicit run-time check, and does not catch the typical type errors writing programs. It helps with simple scripts, but not with programs. You don't have to worry. If you don't like to use types, don't use it. Nothing will change. It will only compile-time optimize and check the cases where someone added the types. Of course the standard library is free to add type-optimized versions later, as e.g some Common Lisp's did with their arrays and vectors. But this was done mostly in the compiler, not in the library itself.
- wirrbel 12y agoYou are right about optimizations, there are a lot of situations where type annotations could greatly help the compiler. I just do not have the feeling that performance optimizations in CPython are the reason for Guido's proposal. It rather seems to be motivated for development tooling. Is `for i in xrange(10000):` especially optimized in python at the moment? I doubt it and those low hanging fruits could be tackled with some explicit pattern matching. (I probably should do my homework now and dive into the python source code).
- tiffanyh 12y agoLua The more I read Armin's posts, the more I believe he should switch to Lua. It has all the core features he wants: - simple design - fast - consistent behavior In addition to what's mentioned above, LuaJIT is a marvelously designed JIT (please donate to the project [1]. Let's keep allowing Mike Pall to have a livelihood) [1] http://luajit.org/sponsors.html http://luajit.org/sponsors.html
- cygx 12y agoI find it interesting that this is exactly what Perl6 tried to handle gracefully, both on the technical side (a type system that supports both static and dynamic typing) as well as on the practical side (a re-implementation from scratch with some measure of interoperability). However, they did not set out to just design the next version of Perl, but the last version, reasoning that if you have proper extension mechanism in place, you won't have to do a reboot ever again. This resulted in gradual typing (which sometimes needs to fall-back to runtime checks), a pluggable syntax with extensible grammar, a flexible meta-object protocol, default numeric types that are objects (rationals or bigints), lazy list, reified language construct (variables as container objects) and other stuff that makes a straight-forward implementation horribly slow.
- ForHackernews 12y agoCan somebody explain in greater detail what this means: > This is true for the CPython interpreter world, but not true for Python the language. That these are not the same things is disappointing but generally the case. My understanding was that the CPython interpreter is considered the "reference" implementation of Python, and that (except for bugs) it defined Correct Behavior for Python-the-language.
- kylebgorman 12y agoMy hope is that Guido's plan to incorporate the type declaration module (`types`, a subcomponent of mypy) will encourage the Python team to clean up the issues brought up in TFA.