Re: [Python-Dev] SyntaxError: can't assign to function call
At 12:28 PM 8/10/2006 -0700, Guido van Rossum wrote:
On Aug 10, 2006, at 12:31 PM, Phillip J. Eby wrote:
Honestly, it might make more sense to get rid of augmented assignment in Py3K rather than to add this. It seems that the need for something like this springs primarily from the existence of augmented assignment.
I assume this was meant tongue-in-cheek.
Not entirely, no.
I see no reason to get rid of +=. The opportunity for hypergeneralization (== ill-advised generalization based on the misunderstanding of some mechanism) does not automatically mean a mechanism should not be added (although it can sometimes be a warning sign).
I think it's a warning sign because I *know* what augmented assignment's semantics are supposed to be and I *still* try to use it with setdefault() sometimes -- but only when I'm doing an augmented assignment. I never mistakenly try to assign to a function call in any other circumstance. However, I'm also not clear that trying to assign to a function call *is* ill-advised. One of the things that attracted me to Python in the first place is that it had a lot of features that would be considered "hypergeneralization" in other languages, e.g. the ability to create your own sequences, mappings, and callable objects in the first place. That being said, the benefit of hypergeneralizing assignment seems small compared to its price. So eliminating augmented assignment seems a more attractive way to get rid of the nuisance of the perennially repeated proposals to "fix" or otherwise extend it. Sometimes it seems like half the time I want to use augmented assignment, I can't use it anyway for one reason or another, so it doesn't seem like that big of a loss.
On 8/10/06, Phillip J. Eby <pje@telecommunity.com> wrote:
That being said, the benefit of hypergeneralizing assignment seems small compared to its price. So eliminating augmented assignment seems a more attractive way to get rid of the nuisance of the perennially repeated proposals to "fix" or otherwise extend it. Sometimes it seems like half the time I want to use augmented assignment, I can't use it anyway for one reason or another, so it doesn't seem like that big of a loss.
I think you are strongly understimating the benefits of augmented assignments. I held out against it for many years. But the users didn't stop asking for it. They're mostly happy. That some aren't happy until we've hypergeneralized it doesn't mean we shouldn't have done it in the first place. (Similar as with lambda. :) -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Phillip J. Eby wrote:
I think it's a warning sign because I *know* what augmented assignment's semantics are supposed to be and I *still* try to use it with setdefault() sometimes -- but only when I'm doing an augmented assignment. I never mistakenly try to assign to a function call in any other circumstance.
I think this problem arises because of the dual semantics of augmented assignment. One tends to have two *different* mental models of what it does, depending on whether the object in question is immutable: (1) For immutable objects: x += y <--> x = x + y (2) For mutable objects: x += y <--> x.__iadd__(y) and it's easy to forget that case (2) also happens to have the side effect of assigning the result back to x, which is usually redundant in the case of an immutable object, and thus to slip into the error of thinking that x(z) += y <---> x(z).__iadd__(y) should be a reasonable thing to expect. And in the case of a mutable result from x(z), it's hard to argue convincingly that it's not reasonable. As to what this is a warning of, maybe it's that the dual semantics were a mistake in the first place, and that there really should have been two sets of operators, e.g. x += y <---> x = x + y # literally x +: y <---> x.__iadd__(y) # with *no* assignment The +: family of operators would then just be normal infix operators, not assignments at all, and one would be able to say x(z) +: y without any trouble (provided the result of x(z) were mutable, since immutables would not have an __iadd__ method at all). Another benefit to this is that the +: operators would be usable on objects in an outer scope, since they are not assignments and would therefore not imply the localness of anything. Something to consider for Py3k? PS: Why an extra set of operators, rather than ordinary methods? One of the motivations for the augmented assignment operators was Numeric and the desire to be able to express in-place operations on arrays concisely. The +: family would fill this need. PPS: Yes, I know the use of : might be ill-advised. It's just an example - any other concise notation would do as well. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+
-1. I just don't think we should add more operators -- it'll just cause more question marks on users' faces... --Guido On 8/10/06, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Phillip J. Eby wrote:
I think it's a warning sign because I *know* what augmented assignment's semantics are supposed to be and I *still* try to use it with setdefault() sometimes -- but only when I'm doing an augmented assignment. I never mistakenly try to assign to a function call in any other circumstance.
I think this problem arises because of the dual semantics of augmented assignment. One tends to have two *different* mental models of what it does, depending on whether the object in question is immutable:
(1) For immutable objects:
x += y <--> x = x + y
(2) For mutable objects:
x += y <--> x.__iadd__(y)
and it's easy to forget that case (2) also happens to have the side effect of assigning the result back to x, which is usually redundant in the case of an immutable object, and thus to slip into the error of thinking that
x(z) += y <---> x(z).__iadd__(y)
should be a reasonable thing to expect. And in the case of a mutable result from x(z), it's hard to argue convincingly that it's not reasonable.
As to what this is a warning of, maybe it's that the dual semantics were a mistake in the first place, and that there really should have been two sets of operators, e.g.
x += y <---> x = x + y # literally
x +: y <---> x.__iadd__(y) # with *no* assignment
The +: family of operators would then just be normal infix operators, not assignments at all, and one would be able to say
x(z) +: y
without any trouble (provided the result of x(z) were mutable, since immutables would not have an __iadd__ method at all).
Another benefit to this is that the +: operators would be usable on objects in an outer scope, since they are not assignments and would therefore not imply the localness of anything.
Something to consider for Py3k?
PS: Why an extra set of operators, rather than ordinary methods? One of the motivations for the augmented assignment operators was Numeric and the desire to be able to express in-place operations on arrays concisely. The +: family would fill this need.
PPS: Yes, I know the use of : might be ill-advised. It's just an example - any other concise notation would do as well.
-- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Fri, Aug 11, 2006, Greg Ewing wrote:
Phillip J. Eby wrote:
I think it's a warning sign because I *know* what augmented assignment's semantics are supposed to be and I *still* try to use it with setdefault() sometimes -- but only when I'm doing an augmented assignment. I never mistakenly try to assign to a function call in any other circumstance.
I think this problem arises because of the dual semantics of augmented assignment. One tends to have two *different* mental models of what it does, depending on whether the object in question is immutable:
(1) For immutable objects:
x += y <--> x = x + y
(2) For mutable objects:
x += y <--> x.__iadd__(y)
What I try to do is always remember that x += y <--> x = x.__iadd__(y) which mostly solves the problem. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian W. Kernighan
On Aug 10, 2006, at 4:57 PM, Phillip J. Eby wrote:
However, I'm also not clear that trying to assign to a function call *is* ill-advised. One of the things that attracted me to Python in the first place is that it had a lot of features that would be considered "hypergeneralization" in other languages, e.g. the ability to create your own sequences, mappings, and callable objects in the first place.
That being said, the benefit of hypergeneralizing assignment seems small compared to its price.
Well, it's a mostly obvious extension of an existing idea, so the price doesn't seem all that high. The main problem is that so far, there have been 0 convincing use cases. So no matter how moderate the price, it's definitely bigger than the benefit. But anyhow, speaking of hypergeneralization...since this has 0 use cases anyhow, might as well hyperhypergeneralize it... Well, why should assignment be limited to only local variables, item access, and function calls. Why shouldn't you be able to potentially assign to _any_ expression! Since x + a turns into (very roughly...) x.__add__(a), then, x + a = 5 could turn into x.__add__.__setcall__(5, a). Of course, since normal __add__ functions don't have a __setcall__, doing this will raise an error. But, a user defined __add__ could have one! And what would such a user defined __add__.__setcall__ actually *do*? Well, that would be a use case, and I sure don't have any of those! Ta Da. Who's going to make the patch? ;) James
On 8/10/06, James Y Knight <foom@fuhm.net> wrote:
On Aug 10, 2006, at 4:57 PM, Phillip J. Eby wrote:
That being said, the benefit of hypergeneralizing assignment seems small compared to its price.
Well, it's a mostly obvious extension of an existing idea, so the price doesn't seem all that high.
If you still think that, you don't realize the problem with hypergeneralization. The extension is *not* obvious, and there are several problems (as I pointed out before). -- --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (5)
-
Aahz
-
Greg Ewing
-
Guido van Rossum
-
James Y Knight
-
Phillip J. Eby