I will think about more interesting examples weekend, though my time will
probably be more family focused so I might not get any messages of
appreciable length out until sometime next week.

I do get what you are saying on the const vs immutability thing, but I was
thinking that because python works the way it does they would need to be
related. If I have a module level variable, that was intended to be a
constant, like below, it would need both.
SAFETY_THRESHOLD = 100
def func(sys_temp):
    if sys_temp > SAFETY_THRESHOLD:
        turn_on_fan()
Would not want someone outside the module (or someone adding new code years
later in the module) redefining SAFETY_THRESHOLD. Now in something like C,
a const on SAFETY_THRESHOLD would be fine without interior mutability,
because a number is just a type, and thus cant be reassigned. In python it
is a class instance with methods and such (substitute in string aka char[]
or something). However in this case __setself__ (__assign__) would be
plenty as the instances are immutable already. I assumed that there would
be no __setself__ on an int, so to get the same sort of const like behavior
(const + fundamental type) one would need to define MyInt, and make it
interior immutable like python str or int, and also const via __setself__.

Now its possible that I am being silly and not thinking through things
correctly again, I keep stealing moments here or there to work on this
project. If so I am happy to have someone correct me.

Typing this out though does make me think of an interesting idea. If there
was something like __getself__ in addition to __setself__, you could
implement things like MyInt. __getself__ would look something like:

class MyInt:
    def __init__(self, value):
        self.value = value
    def __getself__(self):
        return self.value
    def __setself__(self, value):
        raise ValueError("Cant set MyInt")
x = MyInt(2)
print(x) -> 2
type(x) -> MyInt

Now I have not really thought through how this would work, if it could
work, and how setself and getself may play with each other in execution,
and it that would introduce even more weird behavior. It was just something
that occurred to me when typing above. If they did play well together
though, you could do something interesting like creating a variable that
tracked its history such as:

class HistoricVar:
    def __init__(self, initval):
        self._value
        self.history = []
    def __getself__(self):
        return self._value
    def __setself__(self, value):
        self.history.append(self._value)
        self._value = value
    def go_back_n(self, n):
        for i in range(n):
            self.history.pop()
        self._value = self.history[-1]

x = HistoricVar(1)
print(x) -> 1
x = "hello world'
print(x) -> "hello world"
set_var_to_empty_dict(x)
print(x) -> Dict
x = "14"
getattr(x, 'go_back_n')(2) # <- might need special handling for getattr to
account for getself
print(x) -> "hello world"
try:
    for i in range(10)
        x = x + i
        if x > 17:
            raise ValueError('x cant be larger than 17')
except:
    getattr(x, 'go_back_n')(1)

Caveat to anyone not paying attention ^ that code has not been tried in any
interpreter and the changes have been not made to support it anywhere, if
it is at all possible.

Now I know these are silly examples that could be done in other ways, but
they are musings that fit into the scope of typing out in an email. Like I
said I will see if more interesting things come to me over the weekend. If
anything this thread is a fun and interesting thought experiment and a
useful learning experiment for me to better understand the workings of
python, and for that I thank you for your feed back and attention.
Nate

On Fri, Jun 21, 2019 at 6:24 PM Andrew Barnert <abarn...@yahoo.com> wrote:

> On Jun 21, 2019, at 14:36, nate lust <natel...@linux.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
>
> class Foo:
>     @property
>     def x(self):
>         return self._internal
>     @x.setter
>     def x(self, value):
>         self._internal *= value
>      def __init__(self, x)
>         self._internal = x
>
> a = Foo(4)
> print(a.x)
> 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).
>
> On Fri, Jun 21, 2019 at 4:17 PM Ethan Furman <et...@stoneleaf.us> wrote:
>
>> On 06/20/2019 01:25 PM, nate lust wrote:
>>
>> >  --> class Foo:
>> >  ...     def __init__(self, o):
>> >  ...         self.o = o
>> >  ...     def __setself__(self, v):
>> >  ...         self.v = v
>> >  ...
>>
>> >  --> f = Foo(5)
>> >  --> print(f)
>> >  <__main__.Foo object at 0x7f486bb8d300>
>>
>> >  --> print(f.o)
>> >  5
>>
>> >  >>> print(f.v)
>> >  Traceback (most recent call last):
>> >     File "<stdin>", line 1, in <module>
>> >  AttributeError: 'Foo' object has no attribute 'v'
>>
>> >  --> f = "hello world"
>> >  --> print(f.v)
>> >  hello world
>>
>> >  --> print(f)
>> >  <__main__.Foo object at 0x7f486bb8d300>
>>
>> Thank you for doing the work of a proof-of-concept (and to Andrew Barnert
>> for his excellent write-up).  I think this shows exactly why it's a bad
>> idea -- even though I knew what you were doing, having `f` not be a string
>> after the assignment was extremely surprising.
>>
>> -1
>>
>> --
>> ~Ethan~
>> _______________________________________________
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/AFPG55GOZI2U6FK6N2VXYPAQDIJ36ATM/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
> --
> Nate Lust, PhD.
> Astrophysics Dept.
> Princeton University
>
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/CVYU43PXBRSNIEL2NPIVD5NJKRS7VLK4/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/25ZDB3A6RHICX23PVXKQZMQ2JTFKUCAZ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to