On Jun 21, 2019, at 14:36, nate lust <email@example.com> wrote:
I think it is only surprising because it is not something that is familiar.
Part of the problem may be that in your toy example, there really is no reason to overload assignment, so it’s surprising even after you get what it’s doing. If you worked out a more realistic example and demonstrated that with your patch, it might feel a lot less disconcerting.
I feel even less convinced by your other potential uses, but again, if one of them were actually worked out, it might be quite different..
It's not like python python doesn't already have other assignment with different behaviors, for instance:
a = "hello world"
a = 6
print(a) -> 6
def x(self, value):
self._internal *= value
def __init__(self, x)
self._internal = x
a = Foo(4)
a.x = 6
print(a.x) -> 24
This is surprising, but it doesn't mean properties are not useful.
If this were the example given for why properties with setters should exist, it would probably get a -1 from everyone.
But it doesn’t take much to turn this into an example that’s a lot more convincing. For example:
self.ui.slider = BoundedIntegralSlider(0, 100)
self.ui.slider.value = 101
print(self.ui.slider.value) # 100
self.ui.slider.value = sqrt(10)
print(self.ui.slider.value) # 3
The same kind of thing may be true for your change.
A few interesting things I thought to do with this behavior are:
- True consts, if at say the module level you create instances of a class that define ___setattr__ and __setself__ (or __assign__, I just went for symmetry), and they both passed or raised a value error, then your consts would always be consts.
I think this is confusing consts (values that can’t be replaced) with immutable values (values that can’t be changed). Overriding __setattr__ has nothing to do with constness, while it goes 80% of the way toward immutability.
But also, I think it’s a bit weird for constness to be part of the value in the first place. (In C++ terms, a const variable doesn’t necessarily have a const value or vice-versa.) I think trying to fit it into the value might be what encourages confusing const and immutable.
Also, shouldn’t classes and instances (even of __slots__ or @dataclass) “declare” constants just like modules? If you have to write the same thing completely differently, with different under-the-covers behavior, to accomplish the same basic concept, that’s a bit weird. A module-level @property or module __setattr__ seems like it would be a lot more consistent. (Although I’m not sure how well that ports to locals.)
- More natural syntax for coroutine sendto, or I guess any pipe or proxy like object
Making send look like assignment feels a lot less natural, not more. I’d expect something like <- (as used by most Erlang-inspired languages), but, more importantly, something different from =. Especially since you often do want to pass around and store coros, pipes, channels, etc., and if doing so actually send the coro to another coro because you’d reused the name, that would be very confusing.
If this had existed from the start or early on, it would be perfectly natural to read and use, but for now it would be somewhat shocking (in so far as it gets actually used) and I think that is the biggest minus.
I’m not sure that’s true.
If we were talking about a language that has an lvalue objects-and-variables model but doesn’t allow assignment overloading (like Scala, I think?), sure. Some such languages allow it, some don’t, and it’s a pretty simple readability trade off.
But languages with Smalltalk-style object models (especially those without declarations), not being able to overload assignment feels like a natural consequence: variables don’t have types, so a variable’s type can’t take control. You can’t do it in Smalltalk, or Ruby, or any of the Lisp object systems I know of, etc. So, even if Python had a clever workaround to that from the start, I think it would still feel surprising to most people.
Of course the way descriptors, metaclasses, and a few other things work under the hood feels surprising until you get the point, but Python only has a very small number of such things—and they’re all used to build less surprising surface behavior (e.g., @property makes total sense to a novice, even if the implementation of it looks like black magic).
Nate Lust, PhD.