[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-31 Thread Chris Angelico
On Mon, Nov 1, 2021 at 11:26 AM Steven D'Aprano  wrote:
> What sort of testing and maintenance perspective are you referring to?
> Testing and maintenance of the Python interpreter? Or your own code?
>
> If it is your own code then this proposal will have no effect on your
> testing and maintenance. You already have tests, don't you? Then they
> will work the same way whether your functions use late-bound defaults or
> not. If you don't have tests, then the tests that you don't have will
> continue to not work the same as they currently don't work.

For the record: Out of 430 test files in the CPython test suite, only
eight failed after I finished my first version of the implementation.
That's a lot of tests that don't even care.

(Some of those failures indicate actual problems that I needed to fix,
or still need to. A couple are simple and very rigid tests that check
things like the size of a function object. I don't think any of them
indicate actual problems in any place other than the code I actually
need to change - the parser, executor, and the inspect module.)

Most code won't even be aware of this change.

ChrisA
___
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/67XLC2RESR5QLWNJGWQVSYF7XQCTEAWS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-31 Thread Steven D'Aprano
On Sun, Oct 31, 2021 at 09:20:32PM +0100, Sven R. Kunze wrote:

> People on the threads said that they simply want to initialize an empty 
> list [] by a desire to avoid the None scheme.
> 
> I would rather solve those kind of issues than help to squeeze 
> complicated logic into default parameters. But that's just my take on it 
> looking from testing and maintenance perspective here.

Sorry Sven, I'm not sure I understand you. Are you suggesting that it is 
simpler and easier to create a whole new execution model for Python, 
involving a general mechanism for delayed evaluation of expressions, to 
solve the mutable list default problem, than to merely add late-bound 
defaults to functions?

What sort of testing and maintenance perspective are you referring to? 
Testing and maintenance of the Python interpreter? Or your own code?

If it is your own code then this proposal will have no effect on your 
testing and maintenance. You already have tests, don't you? Then they 
will work the same way whether your functions use late-bound defaults or 
not. If you don't have tests, then the tests that you don't have will 
continue to not work the same as they currently don't work.

Whether your functions use the proposed new late bound defaults, or the 
legacy work-around pseudo-late bound defaults using a sentinel, is a 
matter of your functions' internal implementation. It's not something 
that you should write a doctest or unittest or regression test for:

def test_late_bound_default_is_used(self):
# Test that late-binding is used for defaults.
...

Pedantry: you may be able to test for it using introspection on the 
function object, but *why* would you do it??? The choice between the 
legacy "check for None" idiom and the proposed new late-binding idiom is 
an implementation detail.

(Except for the case that your API intentionally documents that None is 
usable as an argument, in which case, simply change nothing and your 
code will continue to work as it does today. Including your tests that 
None is actually usable as an argument.)


> Another idea that comes to my mind is that a separate object allows more 
> in terms of the open-closed principle than a fixed syntax used for one 
> single, hopefully best use-case. Thinking here of the call-by-name and 
> call-by-need evaluation.

Call-by-name and call-by-need are, as far as I can tell, specific 
implementations with no intentional behaviour differences that are 
visible to the caller. Unlike call-by-value and call-by-reference, which 
do have intentional behaviour differences.

Call-by-value makes copies of your arguments; call-by-reference allows 
you to modify variables in the caller's scope.


-- 
Steve
___
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/HAWPJLWS6GFBDMSRDKWQKDTJCEQB6VOZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-31 Thread Sven R. Kunze

On 31.10.21 12:34, Chris Angelico wrote:

Google's smarter than that. I've searched for symbols before and found
plenty of good results. For instance, I can search for information
about the @ sign before a function, or independently, for a @ b, and
get information about decorators or matrix multiplication. We don't
need words - especially not words that will break people's code - in
order for people to find information.


It seems we disagree here. :)


It's a completely different feature, and has very different
consequences. It is not a complete replacement for default
expressions. Notably, it can't refer to anything in the caller's
context, without breaking a lot of things about Python's namespacing
model.


People on the threads said that they simply want to initialize an empty 
list [] by a desire to avoid the None scheme.


I would rather solve those kind of issues than help to squeeze 
complicated logic into default parameters. But that's just my take on it 
looking from testing and maintenance perspective here.


Another idea that comes to my mind is that a separate object allows more 
in terms of the open-closed principle than a fixed syntax used for one 
single, hopefully best use-case. Thinking here of the call-by-name and 
call-by-need evaluation. About the namespacing issue: I disagree here 
because it is always possible to interface these kind of variables 
explicitly (like we do with globals, locals, builtins, etc.). So, it 
would be a compatible addition. Still, we talk about default parameters.


Best
Sven


* Trying that searches do not present the word "matrix multiplication"; 
at least not to me.



___
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/MWQDG5S3CSI5Z35QJCHB5G4H6OXRBRMB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-31 Thread Chris Angelico
On Sun, Oct 31, 2021 at 9:24 PM Sven R. Kunze  wrote:
>
> Actually, the "defer:"-syntax is really readable and searchable compared to 
> the cryptic comparison operator used in the proposal. Just thinking towards 
> "googleability".
>

Google's smarter than that. I've searched for symbols before and found
plenty of good results. For instance, I can search for information
about the @ sign before a function, or independently, for a @ b, and
get information about decorators or matrix multiplication. We don't
need words - especially not words that will break people's code - in
order for people to find information.

> Furthermore, the concept is even more general than parameter definition of 
> functions and methods. I guess a lot of people have already tryied to 
> implement this kind of object various times before (proxy objects, 
> transparent futures etc.)
>
> It also would fit the current semantics of default parameters of Python.
>

It's a completely different feature, and has very different
consequences. It is not a complete replacement for default
expressions. Notably, it can't refer to anything in the caller's
context, without breaking a lot of things about Python's namespacing
model.

ChrisA
___
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/ZOZTK2E6CSV4KAWARPNK7BYTOBNQ7OKE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-31 Thread Sven R. Kunze
Actually, the "defer:"-syntax is really readable and searchable compared 
to the cryptic comparison operator used in the proposal. Just thinking 
towards "googleability".


Furthermore, the concept is even more general than parameter definition 
of functions and methods. I guess a lot of people have already tryied to 
implement this kind of object various times before (proxy objects, 
transparent futures etc.)


It also would fit the current semantics of default parameters of Python.

Cheers
Sven

On 24.10.21 16:37, David Mertz, Ph.D. wrote:

On Sun, Oct 24, 2021, 10:11 AM Chris Angelico

Not sure I understand. Your example was something like:

def fn2(thing):
    a, b = 13, 21
    x = 5
    print("Thing is:", thing)

def f(x=defer: a + b):
    a, b = 3, 5
    fn2(defer: x)
    return x

So inside f(), "defer: a + b" will look in f's scope and use the
variables a and b from there, but passing a "defer: x" to fn2 will
use x from f's scope, and then a and b from fn2's?


Yes, basically as you describe. A "deferred object" is basically just 
a string that knows to wrap itself in eval() when accessed (maybe 
Steven's "thunk" is a better term... But definitely something 
first-class, unlike in Algol).


So within fn2() the parameter 'thing' is bound to an object like 
''.


Indeed this means that the 'defer:' or 'thunk' or special symbol 
spelling, has to decide whether the thing being deferred is already 
itself a deferred object. If so, just pass along the identical object 
rather than treat it as a new expression.


At least that's what would feel most intuitive to me. But I'm 
deliberately not pushing a specific syntax. For example, if we didn't 
want to "reuse" the spelling 'defer:' for both creating and passing a 
deferred object, we could have different spellings.


def f(x=defer: a + b):
    a, b = 3, 5
    fn2(noeval: x)
    return x

... I don't like that spelling, but just showing the concept.


___
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/RMHPLSJ3U67I4TCXS4SVSWNDEATHOVDD/
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/RMFANJ5FAGXP2IFYFFWVDYSNXP7CO2QF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deferred evaluation (was: PEP 671: Syntax for late-bound function argument defaults)

2021-10-24 Thread David Mertz, Ph.D.
On Sun, Oct 24, 2021, 10:11 AM Chris Angelico

> Not sure I understand. Your example was something like:
>
> def fn2(thing):
> a, b = 13, 21
> x = 5
> print("Thing is:", thing)
>
> def f(x=defer: a + b):
> a, b = 3, 5
> fn2(defer: x)
> return x
>
> So inside f(), "defer: a + b" will look in f's scope and use the
> variables a and b from there, but passing a "defer: x" to fn2 will use x
> from f's scope, and then a and b from fn2's?
>

Yes, basically as you describe. A "deferred object" is basically just a
string that knows to wrap itself in eval() when accessed (maybe Steven's
"thunk" is a better term... But definitely something first-class, unlike in
Algol).

So within fn2() the parameter 'thing' is bound to an object like ''.

Indeed this means that the 'defer:' or 'thunk' or special symbol spelling,
has to decide whether the thing being deferred is already itself a deferred
object. If so, just pass along the identical object rather than treat it as
a new expression.

At least that's what would feel most intuitive to me. But I'm deliberately
not pushing a specific syntax. For example, if we didn't want to "reuse"
the spelling 'defer:' for both creating and passing a deferred object, we
could have different spellings.

def f(x=defer: a + b):
a, b = 3, 5
fn2(noeval: x)
return x

... I don't like that spelling, but just showing the concept.

>
___
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/RMHPLSJ3U67I4TCXS4SVSWNDEATHOVDD/
Code of Conduct: http://python.org/psf/codeofconduct/