Hello,

On Thu, 17 Dec 2020 10:03:14 +0000
Stestagg <stest...@gmail.com> wrote:

[]

> > > > But still, are there Python implementations which compile
> > > > "(a.b)()" faithfully, with its baseline semantic meaning? Of
> > > > course there're.  
> > >
> > > OK, Paul, why don't you propose a PR and a bug report about it?  
> >
> > But that's not what this talk is about! It's about a new exciting
> > (hmm, we'll see) feature which, turned out, was there all this time,
> > but was overlooked (so, no patches are needed right away). So, I'm
> > asking fellow Python programmers if they recognize it. If they do,
> > we can consider how to get more from that feature, and maybe some
> > patches will be useful. And if they don't, no patches would help.
> >
> >  
> I like it.
> 
> The idea of a 'method call operator' is quite cute, it's an alternate
> way of thinking about the situation that seems to be self-consistent
> (at least on the surface).

Thanks!

> BUT.
> 
> It's only worth talking about alternate interpretations if there's a
> reasonable chance that introducing a new way of thinking about a
> problem will lead to some improvement: either functional enhancement,
> or better abstractions.

By now I already mentioned a few times that the whole motivation to
introduce it is to improve performance of name lookup operations
(specifically, method lookup). And in this regard, it continues on my
earlier posted proposal of the "strict execution
mode" (https://github.com/pycopy/PycoEPs/blob/master/StrictMode.md)

> Do you have concrete ideas about how treating this language construct
> as a new operator might end up bringing tangible benefits?

Yes, under my proposal, "method call operator" will literally call only
methods, where "a method" is defined as "a function lexically contained
within the class definition".

This means that comparing to the current lookup rules, a.b() won't need
to look for "b" inside the "a" instance, but will look straight in
a's class. In other words, the lookup process will be largely
approaching that of C++. Of course, there's still a big difference that
C++ method vtables are indexed by integer id, as all types (and thus,
methods) are known at compiler-time, while we still will need to
maintain method "vdicts", where we map from symbolic method names to the
actual method code. But, that's the price to pain for
dynamic-typedness of the language. In other aspects, many existing
C++-like optimizations of class hierarchies can be applied (if it all
is coupled with the "strict mode part1" proposal above). 

To avoid ambiguity, shadowing class method with instance attributes
won't work:

class Foo:
    def meth(self): pass

o = Foo()
# doesn't work
o.meth = 1


This is not some completely new restriction. For example, following
already doesn't work in Python:

class A:
    pass

o = A()
o.__add__ = lambda self, x: print("me called")

o + A()  # lambda above is never called


So again, a new restriction is nothing but the existing restriction,
applied consistently to all methods, not just dunder methods. And as
it doesn't work with any method, we also can be explicit about it,
instead of "not working silently", like the __add__ example above shows.
So, back to 1st example:


# Leads to AttributeError or RuntimeError
o.meth = 1

That's why, well, it's called "strict mode" - erroneous actions don't
pass silently.

Now, what if you have an object attribute which stores a callable (no
matter is it's bound method, a function, a class, or whatever)?

You will need to call it as "(obj.callable_ref)(arg, kw=val)". This is a
recent lucky improvement over the previous approach I had in mind,
involving resurrecting the apply() function of good old Python1/Python2
days:

apply(obj.callable_ref, (arg,), {"kw": val})


> Somewhat relatedly, I very much appreciate the simplicity and clean
> approach that Python takes with objects (experiencing Ruby briefly
> having written python made this benefit very clear). 

There's very good reason why I apply this effort to Python, as it's
already more stricter/strongly-typed language than most of its popular
cohorts.

> With python 3,
> the distinction between a function and a method has been further
> reduced, and any change that risks moving us away from `obj.meth()`
> being functionally equivalent to `getattr(obj, 'meth')()` or
> `getattr(Cls, 'meth')(obj)` would have to have incredibly strong
> benefits to outweigh the cost of doing so.

The proposal preserves the first-class nature of bound methods, so if
you had `obj.meth()`, you can always write `t = obj.meth; t()`, or the
forms that you show above, with the same effect.

However, the reverse is not true - if you had `obj.attr`, you can't
call value of that attribute as `obj.attr()`, because that's the syntax
to call methods, not attributes. You'll need to write it as
`(obj.attr)()`. That syntax is fully compatible with the existing
Python.

So, a program which adheres to the strict mode restrictions, will also
run in exactly the same way under the standard mode (in particular,
under a Python implementation which doesn't implement the strict mode).


> 
> Steve
> 

[]

-- 
Best regards,
 Paul                          mailto:pmis...@gmail.com
_______________________________________________
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/J65VK7E46SGAJ2Z2KAPJQRK6QIULV45E/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to