No implicit variable declarations

There are several problems with Python's implicit variable declaration. Just one tiny mistake, like assigning to SpamEggs instead of spamEggs will create a new variable SpamEggs, and spamEggs will hold a stale value. Two statements should be added to Python: (1) a statement that specifies that implicit declaration by assignment should be disabled, like Fortran's "implicit none", and (2) a variable declaration statement, a la "var spamEggs". Trying to assign to a non-existent variable would, of course, cause an error. If the non-existent variable's name is close enough to an existing variable's name, the interpreter might suggest the correct name: "Did you mean "spamEggs"?". This idea could even open Python to static typed variables, declared like "var spamEggs as int". This would prevent the stupid but very possible error of assigning "clientName" (a string) to "doorStatus" (a boolean). -rb

On 04/12/2014 10:14 AM, James Nelson wrote:
There are several problems with Python's implicit variable declaration. Just one tiny mistake, like assigning to SpamEggs instead of spamEggs will create a new variable SpamEggs, and spamEggs will hold a stale value.
This is why you should have unit tests.
And also linters [1].
This idea could even open Python to static typed variables, declared like "var spamEggs as int". This would prevent the stupid but very possible error of assigning "clientName" (a string) to "doorStatus" (a boolean).
-1 on the whole thing. -- ~Ethan~ [1] http://stackoverflow.com/q/5611776/208880

Hello James, I see how this would help with avoiding a whole class of errors, but then i also think your two suggestions -- the var and implicit keywords -- would take a great deal of flexibility and expressiveness from the language. Also, Python was never meant to be statically typed, so suggesting static typing so many years after its creation is IMO pointless, even though you're suggesting it to be optional. OTOH I like your idea of suggesting variable names when NameError is raised, but i don't know how easy this is to implement in CPython. I also want to say that the kind of error you're describing never occured to me in practice. The mistake of assigning to the wrong variable name (and not noticing it immediately through an exception) seems to me like something that only occurs when deliberately writing huge cludges of spaghetti-code, or when you're simply not using enough namespaces. -- Markus On Sat, Apr 12, 2014 at 11:14:18AM -0600, James Nelson wrote:

On Sun, Apr 13, 2014 at 3:47 AM, Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
OTOH I like your idea of suggesting variable names when NameError is raised, but i don't know how easy this is to implement in CPython.
There's another proposal in the pipeline, regarding the addition of extra info to various exceptions, and one of the points it makes is that suggestions could be made on NameError (which would probably be a feature wanted more in interactive mode than elsewhere). How easily it can be made truly useful is anyone's guess; I generally find that "Did you mean" lists are more often useless than helpful. ChrisA

Markus Unterwaditzer <markus@...> writes:
Hello James,
I see how this would help with avoiding a whole class of errors, but then
i that
I don't believe that having var and implicit keywords would make the language less flexible -- they are completely optional, remember. If you omit "implicit none" from the beginning of your program you can write your program like you do now, implicit variable declarations and all. In retrospect, statically typed variables does contradict Python's duck typing: it shouldn't matter if it's a float or an integer, as long as you multiply or divide, you're fine, and if you need a specific type, you just check with type(). - JN

On Sat, Apr 12, 2014 at 06:14:04PM +0000, James Nelson wrote:
At which scope should this statement operate? Should it only be allowed at the top of a module (like __future__ imports), or should it operate on a per-function basis? Doing this for the whole process, as i think your usage of the term "program" implies, sounds like a very bad idea to me. Anyway, i think that this idea just doesn't "fit" Python, and "implicit none" kind-of reminds me of the strict mode in Javascript. But other than in Javascript, i don't think Python actually *needs* this. As said, linters cover these problems for me. -- Markus

On Sun, Apr 13, 2014 at 4:53 AM, Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
As it's something that doesn't change bytecode execution (other than the extra info on NameError, which as mentioned can be done regardless of this proposal) but effects a change to syntax, I would recommend it be per-module, like a future directive. ChrisA

On Apr 12, 2014, at 11:14, James Nelson <retrobanana.jn@gmail.com> wrote:
In retrospect, statically typed variables does contradict Python's duck typing: it shouldn't matter if it's a float or an integer,
Or, more importantly, some type you never thought of--maybe it's a numpy array of int16s...
Actually, even if you need a specific type, you usually want to check with isinstance. Only use type if you explicitly don't want to handle subclasses, ADT registration, etc., which is very rare. Anyway, while you presented this as an afterthought, duck typing is the whole point of dynamic languages like Python. You get the flexibility of a powerful polymorphic type system (like the ones in ML or Haskell, or to a lesser extent C++), while only having to ever think about (and write) simple types (like the ones in pre-generics Java or ActionScript). Of course the cost is that you don't get compile-time type checking. But for many programs, that type checking is nearly useless (at least the Java kind; the Haskell kind is more useful). Anyway, Python has had annotations for years now, and one of the reasons they were added was so someone could write a type-checking linter that statically checked optionally-annotated function and parameter types, and nobody is using it for that. Which implies that nobody is missing it too badly.

On Sun, Apr 13, 2014 at 2:21 PM, Andrew Barnert <abarnert@yahoo.com.dmarc.invalid> wrote:
Of course the cost is that you don't get compile-time type checking. But for many programs, that type checking is nearly useless (at least the Java kind; the Haskell kind is more useful).
Aside: I have periodically had bugs where I omit the first argument of a function (in situations where, had it not been first, it would have been marked optional). In C, those sorts of bugs are often caught by the function signature; in Python, they can be, but only if the function takes a fixed number of args. For instance: void foo(target *destination, const char *msg, int blah=0, int blahblah=0) If you omit the destination, you get an error back straight away, because a string (const char *) can't be converted into a target. The equivalent in Python, though: def foo(destination, msg, blah=0, blahblah=0): would happily assign the args one slot earlier, as long as I provided at least one of the optionals. But this is a fairly narrow case; if both those args were mandatory, the mere count of arguments would trip an error. (Albeit at run-time, not compile-time, but until Python goes to actually run the line of code, it can't know that this is the signature anyway.) ChrisA PS. Neat trick with dmarc.

On Sun, Apr 13, 2014 at 2:56 AM, Chris Angelico <rosuav@gmail.com> wrote:
No you don't! If you're stuck in C89 for one reason or another, all you get is a warning(which most programmers ignore anyway). C++ is much more strict in that regard.
-- Ryan If anybody ever asks me why I prefer C++ to C, my answer will be simple: "It's becauseslejfp23(@#Q*(E*EIdc-SEGFAULT. Wait, I don't think that was nul-terminated."

I think a much more productive approach would be to think about improving pylint by adding support for type comments. Look at how Google's closure compiler does this for JavaScript. --- Bruce (from my phone)

On 04/12/2014 10:14 AM, James Nelson wrote:
There are several problems with Python's implicit variable declaration. Just one tiny mistake, like assigning to SpamEggs instead of spamEggs will create a new variable SpamEggs, and spamEggs will hold a stale value.
This is why you should have unit tests.
And also linters [1].
This idea could even open Python to static typed variables, declared like "var spamEggs as int". This would prevent the stupid but very possible error of assigning "clientName" (a string) to "doorStatus" (a boolean).
-1 on the whole thing. -- ~Ethan~ [1] http://stackoverflow.com/q/5611776/208880

Hello James, I see how this would help with avoiding a whole class of errors, but then i also think your two suggestions -- the var and implicit keywords -- would take a great deal of flexibility and expressiveness from the language. Also, Python was never meant to be statically typed, so suggesting static typing so many years after its creation is IMO pointless, even though you're suggesting it to be optional. OTOH I like your idea of suggesting variable names when NameError is raised, but i don't know how easy this is to implement in CPython. I also want to say that the kind of error you're describing never occured to me in practice. The mistake of assigning to the wrong variable name (and not noticing it immediately through an exception) seems to me like something that only occurs when deliberately writing huge cludges of spaghetti-code, or when you're simply not using enough namespaces. -- Markus On Sat, Apr 12, 2014 at 11:14:18AM -0600, James Nelson wrote:

On Sun, Apr 13, 2014 at 3:47 AM, Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
OTOH I like your idea of suggesting variable names when NameError is raised, but i don't know how easy this is to implement in CPython.
There's another proposal in the pipeline, regarding the addition of extra info to various exceptions, and one of the points it makes is that suggestions could be made on NameError (which would probably be a feature wanted more in interactive mode than elsewhere). How easily it can be made truly useful is anyone's guess; I generally find that "Did you mean" lists are more often useless than helpful. ChrisA

Markus Unterwaditzer <markus@...> writes:
Hello James,
I see how this would help with avoiding a whole class of errors, but then
i that
I don't believe that having var and implicit keywords would make the language less flexible -- they are completely optional, remember. If you omit "implicit none" from the beginning of your program you can write your program like you do now, implicit variable declarations and all. In retrospect, statically typed variables does contradict Python's duck typing: it shouldn't matter if it's a float or an integer, as long as you multiply or divide, you're fine, and if you need a specific type, you just check with type(). - JN

On Sat, Apr 12, 2014 at 06:14:04PM +0000, James Nelson wrote:
At which scope should this statement operate? Should it only be allowed at the top of a module (like __future__ imports), or should it operate on a per-function basis? Doing this for the whole process, as i think your usage of the term "program" implies, sounds like a very bad idea to me. Anyway, i think that this idea just doesn't "fit" Python, and "implicit none" kind-of reminds me of the strict mode in Javascript. But other than in Javascript, i don't think Python actually *needs* this. As said, linters cover these problems for me. -- Markus

On Sun, Apr 13, 2014 at 4:53 AM, Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
As it's something that doesn't change bytecode execution (other than the extra info on NameError, which as mentioned can be done regardless of this proposal) but effects a change to syntax, I would recommend it be per-module, like a future directive. ChrisA

On Apr 12, 2014, at 11:14, James Nelson <retrobanana.jn@gmail.com> wrote:
In retrospect, statically typed variables does contradict Python's duck typing: it shouldn't matter if it's a float or an integer,
Or, more importantly, some type you never thought of--maybe it's a numpy array of int16s...
Actually, even if you need a specific type, you usually want to check with isinstance. Only use type if you explicitly don't want to handle subclasses, ADT registration, etc., which is very rare. Anyway, while you presented this as an afterthought, duck typing is the whole point of dynamic languages like Python. You get the flexibility of a powerful polymorphic type system (like the ones in ML or Haskell, or to a lesser extent C++), while only having to ever think about (and write) simple types (like the ones in pre-generics Java or ActionScript). Of course the cost is that you don't get compile-time type checking. But for many programs, that type checking is nearly useless (at least the Java kind; the Haskell kind is more useful). Anyway, Python has had annotations for years now, and one of the reasons they were added was so someone could write a type-checking linter that statically checked optionally-annotated function and parameter types, and nobody is using it for that. Which implies that nobody is missing it too badly.

On Sun, Apr 13, 2014 at 2:21 PM, Andrew Barnert <abarnert@yahoo.com.dmarc.invalid> wrote:
Of course the cost is that you don't get compile-time type checking. But for many programs, that type checking is nearly useless (at least the Java kind; the Haskell kind is more useful).
Aside: I have periodically had bugs where I omit the first argument of a function (in situations where, had it not been first, it would have been marked optional). In C, those sorts of bugs are often caught by the function signature; in Python, they can be, but only if the function takes a fixed number of args. For instance: void foo(target *destination, const char *msg, int blah=0, int blahblah=0) If you omit the destination, you get an error back straight away, because a string (const char *) can't be converted into a target. The equivalent in Python, though: def foo(destination, msg, blah=0, blahblah=0): would happily assign the args one slot earlier, as long as I provided at least one of the optionals. But this is a fairly narrow case; if both those args were mandatory, the mere count of arguments would trip an error. (Albeit at run-time, not compile-time, but until Python goes to actually run the line of code, it can't know that this is the signature anyway.) ChrisA PS. Neat trick with dmarc.

On Sun, Apr 13, 2014 at 2:56 AM, Chris Angelico <rosuav@gmail.com> wrote:
No you don't! If you're stuck in C89 for one reason or another, all you get is a warning(which most programmers ignore anyway). C++ is much more strict in that regard.
-- Ryan If anybody ever asks me why I prefer C++ to C, my answer will be simple: "It's becauseslejfp23(@#Q*(E*EIdc-SEGFAULT. Wait, I don't think that was nul-terminated."

I think a much more productive approach would be to think about improving pylint by adding support for type comments. Look at how Google's closure compiler does this for JavaScript. --- Bruce (from my phone)
participants (8)
-
Andrew Barnert
-
Bruce Leban
-
Chris Angelico
-
Ethan Furman
-
James Nelson
-
Markus Unterwaditzer
-
Ryan
-
Ryan Gonzalez