:Hello all,
I am sorry to send this out to the list and then be so silent, work and
children and all. I am going to try and address the issues raised in this
thread, with apologies if I miss someones issue. Some of these are
addressed in the documentation I wrote, but I know I can't expect people to
take their time to go off and read a lot of material, I am thankful enough
for the time that people put even into reading and responding. This message
might get long, again, my apologies. I have put names by the response to
that person,  so you can read your section. The response may refer to other
responses, but this was long enough without duplication. Again I might not
have been completely through with each response in light of the length, but
tried to hit the high points and conceptual discussions, if not the details.

For these responses I may refer to some of the demos here:
https://github.com/natelust/CloakingVarWriteup/blob/master/examples.py

Ben Rudiak-Gould:
Your point with iteration is well taken. Depending on the variable bound,
it may end up transparent to you without you needing to care, as in the
case of something like my HistoricVar demo. However it is a fair point,
that it might not be transparent and you could end up with an exception
thrown at some point. I would argue this is not much different than using
any library code where you would need to understand the api, but
documentation is not always up to par, and it is indeed one more thing to
think about or check for.

Your idea of marking a variable with something like metavar is an
interesting idea, and definitely something I am going to think more on. If
this is required for the new behavior in each function where it is used I
don't think that is compatible with how I was envisioning this to work, it
would require more thought. At this point one of the benefits of this type
of metavar, is that I can declare it with whatever side effects I want
(such as a callback on assignment) and pass it into existing third party
code and not need that code to be altered, that code would not care that it
is special.

This is a case where the sense of responsibility is flipped from what you
are worried about though, where I would be responsible for creating an
appropriate variable (like I am for types now) when I am using your
library. I am not sure how that would play well with a keyword at
declaration, except that someone could read my code (or a library using
this type of variable) and see that it was defined in a special way.

Rhodri James:
Your point seems similar Ben's above so perhaps that addresses some of your
points. I think the idea is in what context will this code be used. If I am
a library author then I might not want to expose this type of variable to
outside the api without some sort of annotation.  That does not mean it
could not be really useful inside an api, or for instance used as an
instance level property.

Anders Hovmoller:
Apologies about not getting the accents in your name as I type this. I
appreciate the devils advocate stance. If this proposal went anywhere or
not, I was hopping to learn a lot through the discussion, and process.
Continuing the discussion really helps to that end.

Chris Angelico:
In my proposal you are correct that in functions such as:
def f1():
    x = metavar()
    return x
def f2():
    return metavar()

would not have worked as expected. As soon that the variable became bound
to the name, the LOAD operations that happened before a RETURN operation
would call __getself__ and the result would be returned. A built in method
wold have been required to get to the underlying object, such as in
def f3():
    x = metavar()
    return getcloaked('x')

 This means that those two functions would have resulted in different
returns. (A similar problem would exist for function calls). I was never
entirely happy with this behavior either.

A little while ago I pushed a patch up to my cpython fork that made the
behavior the same as existing python, if you use a metavar in the return
statement, it will be returned from the function to the calling scope,
where it will again behave as a metavar (I also made the same change for
calling a function with a metavar as an argument)

I hope some of the examples I linked to in previous messages helped, but I
am happy to talk more about what the call chain looks like, and how I
intend things to work.

Greg Ewing:
I think some of your points were also addressed above. I am happy to expand
on any of them myself if the above has not addressed them.

Andrew Barnert:
I thank you for also playing devils advocate, and if not providing a "vote
of confidence" then a willingness to make sure my ideas are heard, and that
I have a chance to address and possibly make a better proposal.

Brendan Barnwell:
I can appreciate your position, and might well feel the same if I was a
maintainer of the python code base. However, I will confess I did come away
a little stung by the tone of your message. This may just be because it is
a bit dearer to me, as it is something I have been laboring on.

I tried to write up documentation and do do diligence to have material
ready before coming to the list as to not present a half baked idea. That
said, I certainly was hoping for feedback, either to create a better
proposal, or at least learn something. Whomever is willing to discuss this
with me, I am willing to listen, and or learn. When no one wants to discuss
this, I will not labor the point.

I feel like I have failed in communicating some of my ideas and use cases
to you. In the case you bring up about tracking the history I could indeed
handle tracking in the manor you described, if I was in control of all the
code in use. If however, I created a metavar in one of my own applications,
and passed it down into some preexisting image processing pipeline, there
would be no way for me to control the behavior. WIth my proposal, I get to
define a variable that can meet my needs as well as those of the library I
may be using.

Another example is template expressions from my examples.py (which may be a
bad name, as in c++  they are templates, even though the concept is the
same, the names dont carry over well) By creating a proxy object in an
arithmetic method call, arithmetic operations can be deferred and tracked
inside the proxies. This can be done any number of times, with the final
proxy object being bound to the variable name, i.e.
y = x1+ {<= this creates a proxy object, also with add defined} x2+x3+x4
When y is accessed __getself__ would be called, which could evaluate the
stored expressions in a single loop and returned. This saves creating
temporary object and potentially many expensive python for loops. (The use
case I had mainly in mind is something like an array, but any object could
make use of this)

Another use case is that of defining const. With suitable definitions of
__setself__ and __getself__ a variable could be wrapped that could then not
be rebound. Many modules make use of constants, and it may be advantageous
to protect these through enforcing const-ness. You could put them behind a
class with __setattr__ set, but that only changes the immutability of the
class instance, leaving the instance free to be re-bound. I know the
Pybind11 people struggle with how best to track and account for the lack of
const-ness in python. It would be a fair point to say python should not try
to cater to other projects, but it would not hurt if it was a bonus. I know
even just sticking to pure python, the software stack I work on has a
sufficiently large number of moving pieces, which end user consumers to
worry about, we would be very happy to have a little extra safely from
const.

Overall I am happy to have had feed back from everyone, and am grateful for
the time that they have put in. If nothing else I have learned about what
it takes to communicate ideas to a large number of people who are not
co-located.

On Wed, Jun 26, 2019 at 6:15 PM Andrew Barnert via Python-ideas <
python-ideas@python.org> wrote:

> On Jun 26, 2019, at 13:53, Chris Angelico <ros...@gmail.com> wrote:
>
> > Then in what circumstances will getself NOT be called? What is the
> > point of having an object, if literally every reference to it will
> > result in something else being used?
>
> I think Yanghao has misunderstood the proposal. What Nate actually
> proposed is not that every time the value is accessed it calls __getself__,
> only accesses that are loads from a variable. The infinite regress problem
> is no worse than, say, __getattribute__ usually needing to call a method on
> super or object.
>
> But if I’m right, then your initial refactoring point is still unanswered.
> You can return or otherwise use the value of self or the return of the
> uncloak function or whatever without triggering another call to
> __getself__, but if you refactor the return statement by storing an
> intermediate value in a temporary local variable, accessing that variable
> will trigger another call to __getself__. I assume Nate is working on an
> answer to that along with all the other points that have been raised.
>
> _______________________________________________
> 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/72KYUGOAW7M33BHQ22LBOBYWVVHX4XVF/
> 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/PGFSSGY6TR4SHPPJWFKK4RVJN55AWJMX/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to