Hacker News new | past | comments | ask | show | jobs | submit login

As a somewhat new python programmer (~2 years) coming from statically compiled languages like C#, C++ and Pascal this is something I have thought about a lot. My initial impulse was to wish I had static type checking. But I have come to the conclusion that I just hadn't fully appreciated the differences between interpreted and compiled languages.

The article says that the lack of type checking "lets through" a certain class of errors. However, let's be specific here: there is no build-time static analysis phase in the transformation of python source to executable code. So "lets through" means the same thing whether you have strong typing or not: the error is going to be found at runtime. What we're really talking about, then, is converting AttributeError ("YourObject has no attribute 'startswith'") into something more specific ("Hey, this is supposed to be a string!"). Honestly, that seems to me to be a pretty minor increase in diagnostic information.

So the bottom line for me is that I feel I didn't really understand duck typing. I used to joke that the term actually meant "no typing," and that is in some respects true. But what it really means is "the thing can do what the method expects it to be able to do." If the thing can't serve in the expected role, then the existing errors that result are sufficiently explanatory, imo.




Sure, but you have to wait until runtime to detect those errors. Which means your codebase can have a nasty bug that you might not even notice if you don't run a particular test case. Static typing detects the same thing, but statically at compile time.


Yes, but there is no compile time in python. Are we discussing type checking in python, or another language, or some ideal hybrid? I don't need to be convinced of the value of static type checking in compiled languages.


Sure there is. When do you think parse errors happen? All languages are compiled in one way or another.


Yes, but that's not a very useful observation. I think most developers understand that there is a process to transform source code into executable format. The distinction between interpreted and compiled languages, as commonly understood, is precisely about when that happens. There is a "compilation" step in python, but it happens when the code is executed, and therefore there is not a distinct "compile time" step during which a programmer has an opportunity to detect errors and prevent them from occurring at runtime. In any case, we're slicing hairs here, so in defense of my position I'll simply note that if your definition is sufficient, then there is no need to distinguish between interpreted and compiled languages at all.


That's simply not true. There is a compilation step in python that is completely distinct from the runtime (i.e. when the bytecode files are compiled). There's nothing special about python that prevents static compile time analysis from happening.


Oh, and to address your other point: the line between compiled and interpreted languages has been blurry since day one, and it's only getting blurrier. No modern, highly-used interpreted language gets by these days without compilation to bytecode. Rather than "compilation vs. interpretation", the battle should be "interpretation vs. native execution", which is more meaningful, but the line there is actually still pretty blurry (see JIT compilation, which straddles that line).


I understand your point. There is a step that compiles python source to bytecode, and it does take place before the bytecode is executed. I just think this is a somewhat pedantic observation. A large part of the value of the language lies in the immediacy of its "interpreted" nature (I'll put that in quotes from now on, thanks to you :)). You run the script and it either fails or executes. In the version of python I use on Ubuntu scripts aren't compiled to bytecode for the first time until they are imported, so other code in the project has likely already run before the compiler would have a chance to review the use of types in the imported module. There isn't a project-wide process of compiling all the files and making sure everything is used correctly before any code executes. Maybe it could be made to work that way, but wouldn't that alter the language and the way it is used? In the end I come back to: is AttributeError really not descriptive enough? You can have the last word here.


Okay. AttributeError is good enough, except when it's not. Python is designed in such a way that makes you actively seek out AttributeErrors, rather than having them diagnosed at compile-time. If that works for you, then that's great, but it doesn't always work. Whether it's in the main branch of CPython, or some sort of experimental fork, or some completely distinct static analysis tool, Pythonistas should support efforts to add (potentially optional) increased static checking to the Python interpreter, because it's a good thing.

Will it fit in with the current Python ecosystem? Will it have to change the way the language is used? Maybe, but that doesn't mean we shouldn't experiment with static analysis. We're hackers, after all, and this is something that probably deserves to be hacked on.


The py_compile module allows you to compile Python to bytecode files without executing the code. This isn't the usual way of doing things, but it works well to add separation between compile-time and run-time if desired.


The issue is about when the error is discovered.

You can have "duck typing" in Haskell, for example, using type-classes.

Instead of "letting the errors through" to run-time, you detect them at compile-time.


Yes, but I am talking about python as it is now, not what it might be if it combined the features of other languages. I don't know anything beyond the most basic characteristics of Haskell, so I can't really comment further.


Obviously there are some differences, but type classes are pretty similar to the way python normally works - type classes specify methods that a type has to have. So in the case of 'print', the type specifies that print can be called on anything that implements the method that turns a value into a string. The neat thing, of course, is that if you try to call it on something that doesn't implement that method, you get a compile error (and with proper tooling, I actually see red squiggles in my editor if I make this mistake, which is about as good as it can get).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: