[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Christopher Barker
On Sun, Dec 5, 2021 at 10:38 AM David Mertz, Ph.D. 
wrote:

> I first discussed the idea of a "generalized deferred object/type" on this
> list at least two years ago, probably more than three (I haven't looked
> through archives lately to be sure the dates). The idea got some vague
> interest, but I was too lazy, or too busy, or whatever, to write an actual
> PEP or implementation.
>

I don’t think a full PEP is required at this point, but throughout this
discussion, the idea of a deferred object being a better solution to this
same problem has been brought up.

My sense it that some folks think if we want late-bound defaults, we really
should just do deferred objects.

But I honestly don’t get it. My idea of a deferred object would be quite
different that this, would not be a great replacement for this, and could
quite happily co-exist with this idea. Clearly I’m missing something.

So I think a paragraph or two explaining what is meant by defers objects,
and how they’d be a better way to address late-bound defaults would be very
helpful to the conversation.

It's fine to criticize my inaction in advancing the more general idea. But
> the result of my failing isn't "therefore PEP 671 should be adopted" as you
> keep claiming.
>

Of course not— but you (and I honk others) have used the idea of the
possibility of some future deferred construct being a reason  to reject
this idea. So you have some obligation to explain.

PEP 671 is very much the same. It does something worthwhile. But it does
> vastly less than needed to warrant new syntax and semantics.
>

I’m personally ambivalent about that at this point, but you can make that
case without referring to some possible new feature.

-CHB


-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/S6FMYYMFUDEDG2BYFCR27JVNS6MFVBDO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Inada Naoki
I read PEP 671 today, and I feel PEP 671 is not as useful as someone expected.

For example, PEP 671 has this example:

   def bisect_right(a, x, lo=0, hi=>len(a), *, key=None):

But I think we can not change the signature for backward
compatibility. For example,

   def search(self, x, lo=0, hi=None):
return bisect_right(self._data, x, lo=lo, hi=hi)

If we just change the signature of bisect_right, this wrapper method
will be broken.
So bisect_right should support None for several versions and emit
frustrating DeprecationWarning.
I don't think this change has good cost/performance.

Additionally, this example illustrates that PEP 671 is not wrapper
functions friendly.
If the wrapped functions uses PEP 671, wrapper functions should:

* Copy & paste all default expressions, or
  * But default expression may contain module private variables...
* Use **kwds and hide real signatures.

I have not read all of PEP 671 threads so I am sorry if this is
already discussed.
But this topic is not covered in current PEP 671 yet.

Generally speaking, I don't want to add anything to Python language
that makes Python more complex.
But if I chose one PEP, I prefer PEP 505 than PEP 671.
PEP 505 can be used for default parameters (e.g. `hi ??= len(a)`)  and
many other places.
I feel it has far better benefit / language complexity ratio.

Regards,
-- 
Inada Naoki  
___
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/JRIKPS5GCMTHUX25UVBBIQ527ZI6VZHN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 review of default arguments evaluation in other languages

2021-12-05 Thread David Mertz, Ph.D.
On Sun, Dec 5, 2021 at 6:44 PM Steven D'Aprano  wrote:

> How do you get nine in the first place? Putting aside *args and
> **kwargs, the existing parameter matrix is either 3x2 or 3x2x∞ depending
> on whether you include types as part of the matrix.
> which makes 3x2 = 6, not 9. Adding a distinction between early and late
> defaults would make it 3x3=9, not 18.
>

I probably counted wrong.  I wrote it late last night in my timezone.  I
think trying again, we actually have this currently:

position-only, no default
position-only, early default
position-or-keyword, no default
position-or-keyword, early default
keyword-only, no default  (weird one that I've definitely never used before
just now)
keyword-only, early default

Under the proposal we'd add:

position-only, late default
position-or-keyword, late default
keyword-only, late default

It's not nearly as much as I was thinking.  Of course, it *is* a 50%
increase in the number of parameter types.  Still, that's not the main
reason I oppose the PEP.  I don't really think any of these are fully
orthogonal.  But the number isn't absurdly large.

Hmm... I suppose `*args` and `**kws` are also different types as well.  Of
course, defaults don't make sense for those. So maybe eleven rather than
nine (and lower percentage increase).

--
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
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/24SQ7VNEFFWA5JHFVCVNMJ6KH32I3R6Z/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 review of default arguments evaluation in other languages

2021-12-05 Thread Finn Mason
On Sun, Dec 5, 2021, 12:11 PM Brendan Barnwell 
wrote:

> On 2021-12-04 20:01, David Mertz, Ph.D. wrote:
> >
> > There are perfectly good ways to "fake" either one if you only have the
> > other. Probably more work is needed to simulate early binding, but there
> > are ways to achieve the same effect.
> >
> > However, that language would not be Python. That ship sailed in 1991.
> > What's being discussed here isn't changing the behavior of binding in
> > `def f(foo=bar)`.
> >
> > Instead, it's a discussion of adding ADDITIONAL syntax for late-binding
> > behavior. I think the proposed syntax is the worst of all the options
> > discussed. But the real issue is that the cases where it is relevant are
> > vanishingly rate, and the extra cognitive, teaching, and maintenance
> > burden is significant.
>
> This is a key point that I mentioned in another message (although
> that
> message doesn't seem to have reaches the list for some reason).
> Steven's list is very useful but I don't see any mention there of
> languages that allow BOTH late-binding and early-binding, and
> distinguishes them with some kind of syntactic flag in the signature.
>

Is its not being done before really a good argument against it? It may be
that there simply hasn't been a need in the other languages.

Also, on a kind of side note, what would be a situation where early binding
is advantageous to late binding? I can't think of one off the top of my
head.

-- 
> Brendan Barnwell
> "Do not follow where the path may lead.  Go, instead, where there is no
> path, and leave a trail."
> --author unknown
> ___
> 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/WFCIHHCDJBMBX7J4SNHBNMXTHIP7SJ6D/
> Code of Conduct: http://python.org/psf/codeofconduct/


--
Finn (Mobile)
___
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/6H5K6SGUDIXPISJVG4SYP2PCGWCWPTRI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 review of default arguments evaluation in other languages

2021-12-05 Thread Steven D'Aprano
On Sat, Dec 04, 2021 at 11:39:00PM -0500, David Mertz, Ph.D. wrote:

> Wow! That's an even bigger teaching nightmare than I envisioned in  my
> prior post.  Nine (3x3) different kinds of parameters is already too big of
> a cognitive burden.  Doubling that to 18 kinds makes me shudder. I admit I
> sort of blocked out the positional-only defaults thing.

How do you get nine in the first place? Putting aside *args and 
**kwargs, the existing parameter matrix is either 3x2 or 3x2x∞ depending 
on whether you include types as part of the matrix.

There are three calling conventions for parameters:

- positional only
- positional or keyword
- keyword only

and currently two states:

- no default
- default

which makes 3x2 = 6, not 9. Adding a distinction between early and late 
defaults would make it 3x3=9, not 18.

But surely you don't teach those six (or nine) permutations as 
*independent* features to be learned by rote as separate concepts? Of 
course when you enumerate through all the possibilities, you get six 
seperate choices (positional only with no default, etc), but I would 
hope you aren't teaching them as six independent concepts!

The calling convention and the presence of a default are concepts which 
are orthogonal to each other, so we need only teach them as two choices:

- choose a calling convention (and by all means leave out positional 
  only in an introductory course for beginners);

- choose whether or not to supply a default.

If the PEP is accepted, it doesn't double the number of choices. It just 
adds one more:

- choose between no default, early default or late default.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread 2QdxY4RzWzUUiLuE
On 2021-12-06 at 02:15:36 +1100,
Chris Angelico  wrote:

> On Mon, Dec 6, 2021 at 1:48 AM <2qdxy4rzwzuui...@potatochowder.com> wrote:
> >
> > On 2021-12-05 at 20:30:53 +1100,
> > Chris Angelico  wrote:
> >

[...]

> > > https://pyauth.github.io/pyotp/#time-based-otps
> >
> > I agree.  *Not* conflating timestamps and event IDs is a good thing!
> > APIs and libraries like that are making my point:  the very notion of
> > "overriding the current time" is a bad one.  The notion of "defaulting
> > to the current time" might be okay, in some systems, until it isn't.
> 
> Time-based OTPs are using timestamps. That's what they do. Defaulting
> to the current time is *precisely* how most 2FA systems work. Being
> able to override the time is useful primarily for testing. So for the
> TOTP case, I would say that "timestamp=>time.time()" is the perfect
> way to spell it.

If time-based OTPs use timestamps, then why is there a timestamp
parameter at all?  "Current time" is part of the function, not part of
the API.

Testing functions like that is another problem; adding parameters to the
API does not solve it.  IMO, a better solution is a test harness that
can provide a known "current time" value.

[...]

> I don't know why you'd have something in a logger that lets you
> configure the time, but my guess would be that it's the same thing:
> you can unit-test the logger with consistent inputs. For instance:
> 
> def format_log_line(event, time=>current_time(), host=>get_host()):
> return ...

It's not a question of configuring *the* time, it's a question of
recognizing that there's more than one time:  the time the event
occurred is different from the time the event is logged.  Yes, in many
cases in many systems, it's a difference without a distinction.  In
other systems, timestamps added by loggers are wholly irrelevant.

Out of curiosity, why did you make host a late-binding parameter?

> # shorthand, obv you'd be using a proper testing framework
> assert format_log_line({...}, time=1638717131, host="example") == "..."
> 
> TBH, I think that defaulting to "event happened right now" is about as
> good a default as you'll ever get. In some situations you'll know when
> the event happened... but honestly, I'd rather know when the log line
> happened too. So if I have an event with an inbuilt timestamp, I'll
> incorporate that into the *body* of the log line, and still have the
> logger add its own timestamp.
> 
> But maybe I've spent too much time rummaging through logs from buggy systems.

In time-critical code, I'm not going to waste resources (time, memory,
CPU cycles) formatting a log entry.  The event occurred and has a
timestamp; formatting and logging will happen in a whole different
context (another thread?  another CPU?  another OS?  the O system at
the time the user asks to look at the logs?).  I'm not denying that
there are times you want both timestamps; I'm denying that you can
always conflate them without losing important information.

I'm sticking to my story, which is no doubt a product of the sorts of
systems I've built (and debugged, and not built):  the apparent use case
of "defaulting to a value that changes, like the current time or a
function-generated ID" is conflating the logic of the function with that
function's API.
___
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/IAG5LLCOOGNLVC54BFVWHV3H2ZO6YYSV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Rob Cliffe via Python-ideas



On 05/12/2021 18:37, David Mertz, Ph.D. wrote:

On Sun, Dec 5, 2021, 12:33 PM Chris Angelico

And quite frankly, the tone of this list is sounding like "shut
up, go away, don't do anything, because there are other proposals
that nobody can be bothered writing up, but if they existed,
they'd be way better than what you're doing". Not exactly
encouraging, since nobody is willing to do the work of writing up
proposals, but is plenty willing to criticize.


I'll write up my proposal:

"Keep the status quo"

All done.

I admit I may be a overly vociferous in my opposition to this 
particular change. But I also think your tone has been rather 
consistently pugnacious, and a bit combative, in dismissing objections 
or disagreements.


I know you genuinely wish to *improve Python*, and believe this PEP 
*would* do so. But I think you've become attached to your idea in a 
way that becomes non-constructive and unlikely to garner support.


For example, your careful exclusion of alternative ideas from the PEP 
feels less than forthcoming. It almost feels like you are trying to 
hide the alternatives from the SC. Obviously, many of them read this 
list, and all of them will think of basically the same ideas others 
have suggested on their own anyway.
I am sure Chris A can answer for himself, but IMO the above is, frankly, 
insulting.  It almost feels like you have run out of arguments and are 
resorting to a personal attack.


I first discussed the idea of a "generalized deferred object/type" on 
this list at least two years ago, probably more than three (I haven't 
looked through archives lately to be sure the dates). The idea got 
some vague interest, but I was too lazy, or too busy, or whatever, to 
write an actual PEP or implementation.


It's fine to criticize my inaction in advancing the more general idea. 
But the result of my failing isn't "therefore PEP 671 should be 
adopted" as you keep claiming. It's just that I haven't done the work 
to flesh out the encompassing idea that would cover late-binding as a 
minor aspect.
Nobody has attempted (or at least completed) a PEP, never mind an 
implementation, of a "generalized deferred object/type", in the last N 
years or decades.  And no reason to suppose that anyone will in the next 
N years or decades.  (I am sure it is very difficult.)  And I think it 
is fair to say that opinion is mixed on the benefits of such a 
proposal.  I think it is also fair to say that such a proposal need not 
be incompatible with PEP 671.
Meanwhile we have a completed PEP and implementation (though obviously 
changes might still be made) that "*would*" "*improve Python*".


As an analogy, PEP 275 was written in 2001 and rejected/neglected. PEP 
3103 was rejected in 2006. The very simple case switch on literals was 
thought not to be broad enough to change Python syntax, despite being 
a construct in numerous other programming languages.


Then in 2020, PEP 622 was written, widely discussed and refined, and 
adopted. PEP 622 does EVERYTHING that PEP 275 would have, 19 years 
earlier, and even with pretty much the same syntax. But it also does 
MUCH more as well, and hence was thought to be worth a syntax change.
That is a fair point which, I admit, I struggle somewhat to refute. Let 
me say:
    It would carry more weight if we had a time-line, even a vague one, 
for implementing a "generalized deferred object/type".  Nobody seems to 
be able and prepared to do the work.  Without that, Python could wait 
indefinitely for this (PEP 671's) improvement.
    In my very personal, subjective opinion, PEP 622 feels more like a 
luxury.  Anything that can be done with it could be done with 
pre-existing syntax.  Whereas late-bound defaults feels more like a ... 
hm, "necessity" is obviously the wrong word, I think I  mean "basic 
feature".  (And AFAIU can not really be implemented with existing syntax 
- well, Turing-complete and all that, but I hope you know what I mean.)  
As witness, 12 of the 16 languages that Steven d'Aprano surveyed provide 
it.  YMMV.


Best wishes
Rob Cliffe


PEP 671 is very much the same. It does something worthwhile. But it 
does vastly less than needed to warrant new syntax and semantics. I 
hope it takes less than 19 years, but a generalized deferred construct 
is worth waiting for.


___
Python-ideas mailing list --python-ideas@python.org
To unsubscribe send an email topython-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-ideas@python.org/message/JPCEPJAZ3452ZRNSZLYCAJU4EVAIKJEX/
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 

[Python-ideas] Re: Compiler from python to WebAssembly

2021-12-05 Thread Jonathan Fine
Hi Ricard

Python to web assembly is a good idea that is already being developed.

The first result from this search
https://www.google.com/search?q=python+webassembly
is the project https://github.com/pyodide/pyodide.

Also relevant is https://www.theregister.com/2021/11/30/python_web_wasm/
You loved running JavaScript in your web browser. Now, get ready for Python
scripting

with kind regards

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


[Python-ideas] Re: PEP 671 review of default arguments evaluation in other languages

2021-12-05 Thread Brendan Barnwell

On 2021-12-04 20:01, David Mertz, Ph.D. wrote:


There are perfectly good ways to "fake" either one if you only have the
other. Probably more work is needed to simulate early binding, but there
are ways to achieve the same effect.

However, that language would not be Python. That ship sailed in 1991.
What's being discussed here isn't changing the behavior of binding in
`def f(foo=bar)`.

Instead, it's a discussion of adding ADDITIONAL syntax for late-binding
behavior. I think the proposed syntax is the worst of all the options
discussed. But the real issue is that the cases where it is relevant are
vanishingly rate, and the extra cognitive, teaching, and maintenance
burden is significant.


	This is a key point that I mentioned in another message (although that 
message doesn't seem to have reaches the list for some reason). 
Steven's list is very useful but I don't see any mention there of 
languages that allow BOTH late-binding and early-binding, and 
distinguishes them with some kind of syntactic flag in the signature.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 5:51 AM David Mertz, Ph.D.  wrote:
>
> On Sun, Dec 5, 2021, 1:48 PM Chris Angelico
>>
>> You: "Keep the status quo, all done"
>> Also you: "Let's wait for something better"
>
>
> Now is better than never.
> Although never is often better than *right* now.

Neither of which says "the distant and uncertain future of an
unwritten proposal is better than either now or never". If you JUST
said "keep the status quo, all done", that is a reasonable and
consistent position (which I disagree with, but I fully respect). But
you then taint your claims with this statement that the reason for
keeping the status quo is not that the status quo is better, but that
there is a hypothetical idea that might be even better. That's not
"now is better than never". That's not "never is better than right
now" either.

I think it's time for me to drop this entire topic for a while. This
list is getting more and more noisy and I'm going to stop contributing
to that.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread David Mertz, Ph.D.
On Sun, Dec 5, 2021, 1:48 PM Chris Angelico

> You: "Keep the status quo, all done"
> Also you: "Let's wait for something better"
>

Now is better than never.
Although never is often better than *right* now.
___
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/BHFHNBCNWFZWXZE7MC2Y6OFA5KLREVOL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 5:38 AM David Mertz, Ph.D.  wrote:
>
> On Sun, Dec 5, 2021, 12:33 PM Chris Angelico
>>
>> And quite frankly, the tone of this list is sounding like "shut up, go away, 
>> don't do anything, because there are other proposals that nobody can be 
>> bothered writing up, but if they existed, they'd be way better than what 
>> you're doing". Not exactly encouraging, since nobody is willing to do the 
>> work of writing up proposals, but is plenty willing to criticize.
>
>
> I'll write up my proposal:
>
> "Keep the status quo"
>
> All done.
>
> PEP 671 is very much the same. It does something worthwhile. But it does 
> vastly less than needed to warrant new syntax and semantics. I hope it takes 
> less than 19 years, but a generalized deferred construct is worth waiting for.
>

You: "Keep the status quo, all done"

Also you: "Let's wait for something better"

That's what I take issue with. You are simultaneously telling me that
this proposal is bad because there's another proposal that would be
better, AND saying that you don't want to push for any other proposal.

So you're welcome to keep waiting. Meanwhile, I'm going to try to
actually accomplish something NOW, not wait for some hypothetical
future.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 5:20 AM Christopher Barker  wrote:
>
> On Sun, Dec 5, 2021 at 3:28 AM Chris Angelico  wrote:
>>
>> (That said, though: it would be rather nice to be able to do algebra
>> with function signatures. For instance, you could say "my signature is
>> that function's kwargs plus frobnosticate=42" or "my signature is that
>> function's kwargs minus stdin". But that's a topic for another thread
>> or another day.)
>
>
> Heck, or even " my signature is that other function's signature" -- that is 
> what passing *args, **kwargs does, but you have to look at the implementation 
> to know.
>

Ah, if it's absolutely exactly "that other function's signature", then
set func.__wrapped__ to the other function (that's what
@functools.wraps does to make the signature work). But that's the only
option. You can't do modifications in this way:

def func(*args, **kwargs, frobnosticate=42):
...
basefunc(**args, **kwargs)

def func(*args, **kwargs):
if "stdin" in kwargs:
stdin = kwargs.pop("stdin")
...
basefunc(*args, **kwargs)

You have to do all-or-nothing at the moment. I don't know of a good
way to make this happen, but if someone has a brilliant idea, I'd love
to hear one.

> As it happens, right now, someone on my team is trying out an implementation 
> that uses inspect to grab the signature of superclass methods so that we can 
> have a complete function signature without repeating ourselves all over the 
> place. Not sure that's a good idea, but it would be cool if there were a 
> standard and reliable way to do that.
>

If you mean that it's chasing all the way up the class hierarchy,
building the signature piece by piece, then you're right, there's no
easy way to do that at the moment. Signature algebra would allow you
to do that - you'd have each function say "that function, but these
changes" - but how you specify that is the hard part.

> But yes, topic for another day.

Indeed.

>> > > None is most assuredly not going to trigger a late-bound default.
>>
>> I don't think so, because None doesn't mean "omit this argument". It
>> is a perfectly valid value. There's also no need to say that object()
>> won't trigger late-bound defaults, or 0, or anything else. The only
>> way to cause a default argument to be evaluated is to not pass the
>> argument - as is already the case.
>
>
> But I'd like to see as a (perhaps rejected) idea is to have a new sentinel 
> that does mean undefined.Sure there could be (rare) cases where you would 
> need to have it a valid value, but then maybe you can't use late-bound 
> defaults in that case.
>
> This is very different from None, because it would be new, so no one is 
> already using it for anything else. And sure, folks could choose to use it 
> inappropriately, but consenting adults and all that.

I think that would be more confusion than it's worth. Having an object
with no value is a means of major insanity. I'll give a specific
example of something that frustrated me from JavaScript; this kind of
API is very common:

// If "foo" is present, remove it. Otherwise, add it
classList.toggle("foo")
// Add "foo"
classList.toggle("foo", 1)
// Remove "foo"
classList.toggle("foo", 0)

These are defined using the standard truthiness rules: any true value
will add, any false value will remove. And if you don't pass anything
at all, it toggles.

Next up, consider this:

state = {
"title": "some title",
"is_open": true/false,
"etc": etc,
}

// Check to see if the thing is open or not
if (state.is_open) {...} else {...}

Cool. Nice and easy. Both of these use the truthiness rules. Seems
pretty normal, right?

Unfortunately, there is ONE special value which doesn't behave the
same way: undefined. In an 'if' statement, undefined is falsy, so
you'd go into the 'else' clause. Just like None in Python, just like
every language with a concept of truthiness/falsiness. But in the
toggle() call, undefined is indistinguishable from not passing the
argument at all. So instead of removing, it will toggle.

That specific issue cost me some debugging time, because I didn't even
think to ask the question "why is state.is_open undefined instead of
false" - because in every other way, undefined did indeed behave as if
it were false.

>> Yeah :) I say this because, in JavaScript, there is fundamentally no
>> difference between passing the special value 'undefined' (kinda like
>> None, although there's also null as a separate value) and not passing
>> the argument at all, which means that...
>>
>> function foo(x="hello") {console.log("x is " + x);}
>> foo(undefined);
>> foo(foo.any_unknown_attr);
>>
>> will print "x is hello" twice. I don't want that :)
>
>
> Sure, that's ugly, but isn't the real problem here that  
> foo(foo.any_unknown_attr) doesn't raise an Exception? Would we have that same 
> issue in Python?

Well, true, that particular part of it is handled by that. But in
Python, you might get something from a dictionary using

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread David Mertz, Ph.D.
On Sun, Dec 5, 2021, 12:33 PM Chris Angelico

> And quite frankly, the tone of this list is sounding like "shut up, go
> away, don't do anything, because there are other proposals that nobody can
> be bothered writing up, but if they existed, they'd be way better than what
> you're doing". Not exactly encouraging, since nobody is willing to do the
> work of writing up proposals, but is plenty willing to criticize.
>

I'll write up my proposal:

"Keep the status quo"

All done.

I admit I may be a overly vociferous in my opposition to this particular
change. But I also think your tone has been rather consistently pugnacious,
and a bit combative, in dismissing objections or disagreements.

I know you genuinely wish to improve Python, and believe this PEP would do
so. But I think you've become attached to your idea in a way that becomes
non-constructive and unlikely to garner support.

For example, your careful exclusion of alternative ideas from the PEP feels
less than forthcoming. It almost feels like you are trying to hide the
alternatives from the SC. Obviously, many of them read this list, and all
of them will think of basically the same ideas others have suggested on
their own anyway.

I first discussed the idea of a "generalized deferred object/type" on this
list at least two years ago, probably more than three (I haven't looked
through archives lately to be sure the dates). The idea got some vague
interest, but I was too lazy, or too busy, or whatever, to write an actual
PEP or implementation.

It's fine to criticize my inaction in advancing the more general idea. But
the result of my failing isn't "therefore PEP 671 should be adopted" as you
keep claiming. It's just that I haven't done the work to flesh out the
encompassing idea that would cover late-binding as a minor aspect.

As an analogy, PEP 275 was written in 2001 and rejected/neglected. PEP 3103
was rejected in 2006. The very simple case switch on literals was thought
not to be broad enough to change Python syntax, despite being a construct
in numerous other programming languages.

Then in 2020, PEP 622 was written, widely discussed and refined, and
adopted. PEP 622 does EVERYTHING that PEP 275 would have, 19 years earlier,
and even with pretty much the same syntax. But it also does MUCH more as
well, and hence was thought to be worth a syntax change.

PEP 671 is very much the same. It does something worthwhile. But it does
vastly less than needed to warrant new syntax and semantics. I hope it
takes less than 19 years, but a generalized deferred construct is worth
waiting for.
___
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/JPCEPJAZ3452ZRNSZLYCAJU4EVAIKJEX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Christopher Barker
On Sun, Dec 5, 2021 at 3:28 AM Chris Angelico  wrote:

> (That said, though: it would be rather nice to be able to do algebra
> with function signatures. For instance, you could say "my signature is
> that function's kwargs plus frobnosticate=42" or "my signature is that
> function's kwargs minus stdin". But that's a topic for another thread
> or another day.)
>

Heck, or even " my signature is that other function's signature" -- that is
what passing *args, **kwargs does, but you have to look at the
implementation to know.

As it happens, right now, someone on my team is trying out an
implementation that uses inspect to grab the signature of superclass
methods so that we can have a complete function signature without repeating
ourselves all over the place. Not sure that's a good idea, but it would be
cool if there were a standard and reliable way to do that.

But yes, topic for another day.

> > None is most assuredly not going to trigger a late-bound default.
>
> I don't think so, because None doesn't mean "omit this argument". It
> is a perfectly valid value. There's also no need to say that object()
> won't trigger late-bound defaults, or 0, or anything else. The only
> way to cause a default argument to be evaluated is to not pass the
> argument - as is already the case.
>

But I'd like to see as a (perhaps rejected) idea is to have a new sentinel
that does mean undefined.Sure there could be (rare) cases where you would
need to have it a valid value, but then maybe you can't use late-bound
defaults in that case.

This is very different from None, because it would be new, so no one is
already using it for anything else. And sure, folks could choose to use it
inappropriately, but consenting adults and all that.


> Yeah :) I say this because, in JavaScript, there is fundamentally no
> difference between passing the special value 'undefined' (kinda like
> None, although there's also null as a separate value) and not passing
> the argument at all, which means that...
>
> function foo(x="hello") {console.log("x is " + x);}
> foo(undefined);
> foo(foo.any_unknown_attr);
>
> will print "x is hello" twice. I don't want that :)


Sure, that's ugly, but isn't the real problem here that
foo(foo.any_unknown_attr) doesn't raise an Exception? Would we have that
same issue in Python?

e.g., doesn't Javascript already have:

foo();
foo(foo.any_unknown_attr);

lead to the same thing? whereas in Python, that would raise, yes?

Or is there something special about undefined that I'm missing?
  (sorry, I don't really "get" Javascript)

I personally think more standard special purpose sentinels would be a good
idea, though I understand the arguments made against that in previous
discussions. But this is a little different, because late-bound defaults
are a new thing, so we don't already have a body of code using None, or
anything else for "use the late bound default".

-CHB

-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/AJ4MPX7RWIV4537LH6OXD4KKJXJWCQ35/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Compiler from python to WebAssembly

2021-12-05 Thread Ricard Sanchez Besalduch
Hi

It would be cool to make a compiler from python to WebAssembly. Adapting the 
actual python compiler. And making an interface to interact with the DOM as a 
python library. The final idea is to replace JavaScript with Python. 

With that we could use python in the frontend and in the backend, with Django.
___
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/JYBGCQH76PPKSLWQHE76SOHRHWLGW2EI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 review of default arguments evaluation in other languages

2021-12-05 Thread Rob Cliffe via Python-ideas

On 05/12/2021 04:01, David Mertz, Ph.D. wrote:


The cost here is that EVERY SINGLE student learning Python needs to 
add this new construct to their mental load. EVERY book and tutorial 
needs to be updated. EVERY experienced developer has to spend extra 
effort understanding and writing code.


The COST of implementing this PEP is *quite literally* tens of 
millions of person days. The benefit is a rare savings of two lines of 
function body code or a docstring line.




I think you exaggerate, e.g.:
    - Many students may never use late-binding, and be perfectly happy 
not knowing about it).

    - Not just saving two lines but IMO adding simplicity and clarity
But no matter.
If this were always a compelling argument, Python would *never* be changed.
Best wishes
Rob Cliffe___
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/SYHWVWPOBR2E2L3HVPFO7SOFJ7FMCPCG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Rob Cliffe via Python-ideas



On 05/12/2021 15:16, Steven D'Aprano wrote:

On Wed, Dec 01, 2021 at 12:26:33PM +, Matt del Valle wrote:


I'm sure that people will learn the many uses of the arrow symbols.
After all, people learn Perl and APL :-) Closer to home, we also learn
all the many different uses of the star symbol `*`.


Not to mention the half-dozen or so uses of colon (introduce a suite, 
slicing, dictionary displays, annotations, lambdas).  Anybody still have 
a problem with them?  Raise your hand and I'll give you your money back.

Best wishes
Rob Cliffe
___
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/WE5KC5SUOKPAM3RVC7FO2MNSJTVBJSTB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 4:13 AM Steven D'Aprano  wrote:
>
> On Mon, Dec 06, 2021 at 02:08:46AM +1100, Chris Angelico wrote:
>
> > I want to have them syntactically as part of the body
> > of the function, and semantically as part of the function call.
>
> Then you'll love the status quo, because that's exactly what we have
> now! *wink*

Aand that's what I get for typing emails at 2AM. LOL.
Syntactically as part of the signature of the function, is what I
meant to say. Thanks for the correction.

> > As a function begins executing, a ton of stuff happens, including
> > allocating arguments to parameters, and providing default values for
> > optional parameters that weren't passed.
>
> And neither of those things are part of the function body. They are
> set up *before* the function's code object is called.

Correct. Including handling default values.

> > All I want to change is the way that defaults can be provided.
>
> Right. And the community reaction on this mailing list is underwhelming.
> Apart from Abe, who is rather vigourly in favour of the PEP as it
> stands, I'm not really sure this PEP has much support as it stands now.
>
> And one of the most frequent issues raised is that **all** you want to
> do is change the way that the late defaults can be provided.
>
> You're the PEP author, but maybe you should consider listening to
> community feedback? Just sayin'.

Believe you me, I am listening. And quite frankly, the tone of this
list is sounding like "shut up, go away, don't do anything, because
there are other proposals that nobody can be bothered writing up, but
if they existed, they'd be way better than what you're doing".

Not exactly encouraging, since nobody is willing to do the work of
writing up proposals, but is plenty willing to criticize.

> > Tell me, what's the first bytecode instruction in the function g here?
> >
> > def f(x):
> > print(x)
> > return lambda: x
>
> Why do you think that is an argument against my position? As you said:
>
> > CPython bytecode is an implementation detail, and the fact that
> > there's bytecode to do this or that is not part of the language
> > definition.
>
> Bytecode can and does change.
>
> I'm talking about the language definition: late bound defaults should be
> compiled into their own publicly accessible callable functions. I don't
> care what bytecode is emitted to do that. Whatever it is, it will change
> in the future, without changing the Python semantics one whit.

Yes. So why is it a problem for the default's evaluation to be part of
the function's bytecode? I don't understand why this is such a big
hassle.

> > def func(arg=>_implementation()):
> > ...
> >
> > No magic, just perfectly normal coding practices.
>
> You've just made a good argument against your own PEP. We don't need new
> syntax for late-bound defaults, just use the perfectly normal coding
> practices that have worked fine for 30 years.

Hmm you mean that "arg=>_implementation()" works currently?

You're complaining that complicated argument defaults can't be
separately tested, and that we need magic to do the refactoring for us
and make them testable. I say that, if it needs to be separately
tested, refactor it, and if it's simple enough to not be worth
refactoring, it doesn't get separately tested.

That's an argument against your "break it into a separate magical
subfunction" proposal, but not against the PEP itself.

> Sure. And why should early-bound defaults be available in a publicly
> accessible dunder attribute, when they could be compiled directly into
> the function code object?

Because they're part of the FUNCTION, not the CODE. There's a big
difference. Consider:

for i in range(10):
def func(i=i): ...

There is only one code object. There are multiple function objects,
each with their own early-bound defaults. By definition, since the
defaults are evaluated as part of the function definition, the code to
evaluate that MUST be part of the surrounding context, not the
function being defined.

And it's not introspectable at the moment, only the resulting value
is. You are asking for far more than the language currently offers in
any related context.

> Hell, the entire code object, and most of the function object, could
> be compiled into one great big opaque ball of mud. Aside from standard
> attributes inherited from object, all the function really needs is a
> name and a binary blob of everything else.
>
> But that's not the sort of language we have.
>

Indeed. We have all kinds of useful introspection tools. And
late-bound defaults already have quite a few introspection features,
most notably a source-code-reconstruction of the expression. That's
more than you get for early-bound defaults.

(In discussing this, I have noted a hole in the specification: it
would be nice to have a way to see, on the code object, which args
have late-bound defaults. Consider that a specification bug to be
fixed.)

You're setting the bar for PEP 671 a long 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Steven D'Aprano
On Mon, Dec 06, 2021 at 02:08:46AM +1100, Chris Angelico wrote:

> I want to have them syntactically as part of the body
> of the function, and semantically as part of the function call.

Then you'll love the status quo, because that's exactly what we have 
now! *wink*


> As a function begins executing, a ton of stuff happens, including 
> allocating arguments to parameters, and providing default values for 
> optional parameters that weren't passed.

And neither of those things are part of the function body. They are 
set up *before* the function's code object is called.


> All I want to change is the way that defaults can be provided.

Right. And the community reaction on this mailing list is underwhelming. 
Apart from Abe, who is rather vigourly in favour of the PEP as it 
stands, I'm not really sure this PEP has much support as it stands now.

And one of the most frequent issues raised is that **all** you want to 
do is change the way that the late defaults can be provided.

You're the PEP author, but maybe you should consider listening to 
community feedback? Just sayin'.


> Tell me, what's the first bytecode instruction in the function g here?
>
> def f(x):
> print(x)
> return lambda: x

Why do you think that is an argument against my position? As you said:

> CPython bytecode is an implementation detail, and the fact that
> there's bytecode to do this or that is not part of the language
> definition.

Bytecode can and does change.

I'm talking about the language definition: late bound defaults should be 
compiled into their own publicly accessible callable functions. I don't 
care what bytecode is emitted to do that. Whatever it is, it will change 
in the future, without changing the Python semantics one whit.


> And if you want an _implementation function for external testing,
> you're still welcome to do that.

Oh, thank goodness! I thought your PEP was going to ban the use of 
function calls as the default expression!!! *wink*


> def func(arg=>_implementation()):
> ...
> 
> No magic, just perfectly normal coding practices.

You've just made a good argument against your own PEP. We don't need new 
syntax for late-bound defaults, just use the perfectly normal coding 
practices that have worked fine for 30 years.


> If something's
> important enough to test separately, refactor it into a private
> function so you can call it. Why should this happen automatically for
> late-bound argument defaults? 

Sure. And why should early-bound defaults be available in a publicly 
accessible dunder attribute, when they could be compiled directly into 
the function code object?

Hell, the entire code object, and most of the function object, could 
be compiled into one great big opaque ball of mud. Aside from standard 
attributes inherited from object, all the function really needs is a 
name and a binary blob of everything else.

But that's not the sort of language we have.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 2:56 AM Steven D'Aprano  wrote:
> > > What sort of "behave differently" do you think would prevent us from
> > > introspecting the function object? "Differently" from what?
> >
> > Wrapping it in a function means the walrus would assign in that
> > function's context, not the outer function.
>
> Unless the variable was a cell variable of the outer function. Which I
> think that they need to be. Didn't you already decide that walrus
> assignment has to be in the context of the function?
>
> That's not a rhetorical question, I genuinely don't remember.

Yes, it does, and that won't be the case if you create an invisible
nested function.

> > But this raises a new problem: The function object, when created, MUST
> > know its context. A code object says "this is a nonlocal", and a
> > function object says "when I'm called, this is my context". Which
> > means you can't have a function object that gets called externally,
> > because it's the code, not the function, that is what you need here.
> > And that means it's not directly executable, but it needs a context.
>
> Sorry Chris, I don't understand what you are trying to say here. If I
> take what you are saying literally, I would take you as trying to say
> that closures can never be executed. But they clearly can be, and I know
> that you know that. So obviously I am misunderstanding you.

Closures cannot be executed without a context. Consider:

def f(x=lambda: (a:=[])):
if isinstance(x, FunctionType): x = x()
print(a)

Here's the problem: The name 'a' should be in the context of f, but
that context *does not exist* until f starts executing. As an
early-bound default, like this, it's not going to work, because the
function object has to be fully constructed at function definition
time.

If you try to do this sort of thing with a magical function that is
synthesized as part of late-bound default handling, you'll still need
to figure out when f's context gets formed. Normally, it won't get
formed until the stack frame for f gets constructed - which is when
arguments get assigned to parameters, etc, etc. Trying to call that
inner function without first giving it a context won't work.

And if all you have is a code object without a function, what's the
use? How is it better than just having code in the function itself?

> I don't understand why you think that we can't take one of those
> Late-Bound (LB) functions, which will be a closure, and call it like we
> can call any other closure.
>
> By the time we have access to the LB functions, the owner function will
> exist, so there shouldn't be any problem with the context not existing.

The function will exist. The instance of it won't. Consider this basic
demo of closures:

def counter():
n = 1
def incr():
nonlocal n
n += 1
return n
return incr

Prior to calling counter(), you can disassemble incr's bytecode and
see what it does. But you can't call incr. Its context does not yet
exist. Until you call counter, there is actually no function for incr,
only the code object. And while it is possible to eval() a code
object...

>>> eval(counter.__code__.co_consts[2])
Traceback (most recent call last):
  File "", line 1, in 
TypeError: code object passed to eval() may not contain free variables

... you can't if it has nonlocals, because it needs a context. So if
there's any possibility of nonlocals in latebound argument defaults,
you won't be able to call this externally, which leaves me wondering:
why all this hassle if it isn't even going to work?

> > So, once again, we come right back around to what I have already: code
> > that you can't lift out and call externally. The difference is that,
> > by your proposal, there's a lot more overhead, for the benefit of
> > maybe under some very specific circumstances being able to synthesize
> > the result.
>
> Surely it is the other way around? If you are correct, there are some
> extremely specific cicumstances involving the use of walrus operator in
> two different default expressions such that you cannot call one of the
> two functions, but the 99.99% of straight-forward non-walrus, non-tricky
> default expressions will work perfectly fine as independently callable
> functions.

To be honest, 99.99% of late-bound defaults would probably work just
fine if you simply eval their texts. But that doesn't justify having
functions either.

> > I'm still not convinced that it's as useful as you say. Compare these
> > append-and-return functions:
> >
> > def build1(value, lst=None):
> > if lst is None: lst = []
> [...]
> > In which of them can you introspect the []?
>
> "Here are lots of ways to solve a problem that don't let you test or
> introspect part of your code. Therefore we shouldn't add a feature that
> will let us more easily test and introspect that part of the code."
>
> Yes Chris, I know that emulated late-bound defaults are currently
> effectively invisible at runtime (short of byte-code 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Steven D'Aprano
On Sun, Dec 05, 2021 at 01:19:08PM +1100, Chris Angelico wrote:

> > And if you still think that we should care, we can come up with a more
> > complex trigger condition:
> >
> > - the parameter was flagged as using a late-default;
> > - AND the default is a LB function.
> >
> > Problem solved. Now you can use LB functions as early-bound defaults,
> > and all it costs is to record and check a flag for each parameter. Is it
> > worth it? Dunno.
> 
> Uhh so. the parameter has to be flagged AND the value has to
> be flagged? My current proposal just flags the parameter.

*shrug* Is that a problem? Okay, then we can just flag the parameter, 
and use a plain ol' function with no special co_flag, although we do 
surely still want to give it an attribute `__expression__` to hold the 
source expression.


> So I ask again: what are you gaining by this change?

Separation of concerns. Testing. Cleaner design (the body of the 
function contains only the byte code from the body of the function). 
Testing. Introspection. Testing. You don't have to hack the byte-code of 
the function in order to monkey-patch defaults. Testing.

In case it wasn't obvious, I think that testing is important :-)

Other people might think of other uses.


[...]
> > What sort of "behave differently" do you think would prevent us from
> > introspecting the function object? "Differently" from what?
> 
> Wrapping it in a function means the walrus would assign in that
> function's context, not the outer function.

Unless the variable was a cell variable of the outer function. Which I 
think that they need to be. Didn't you already decide that walrus 
assignment has to be in the context of the function?

That's not a rhetorical question, I genuinely don't remember.


> The obvious solution is to say that, in this context, a is a nonlocal.

Right.


> But this raises a new problem: The function object, when created, MUST
> know its context. A code object says "this is a nonlocal", and a
> function object says "when I'm called, this is my context". Which
> means you can't have a function object that gets called externally,
> because it's the code, not the function, that is what you need here.
> And that means it's not directly executable, but it needs a context.

Sorry Chris, I don't understand what you are trying to say here. If I 
take what you are saying literally, I would take you as trying to say 
that closures can never be executed. But they clearly can be, and I know 
that you know that. So obviously I am misunderstanding you.

I don't understand why you think that we can't take one of those 
Late-Bound (LB) functions, which will be a closure, and call it like we 
can call any other closure.

By the time we have access to the LB functions, the owner function will 
exist, so there shouldn't be any problem with the context not existing.


> So, once again, we come right back around to what I have already: code
> that you can't lift out and call externally. The difference is that,
> by your proposal, there's a lot more overhead, for the benefit of
> maybe under some very specific circumstances being able to synthesize
> the result.

Surely it is the other way around? If you are correct, there are some 
extremely specific cicumstances involving the use of walrus operator in 
two different default expressions such that you cannot call one of the 
two functions, but the 99.99% of straight-forward non-walrus, non-tricky 
default expressions will work perfectly fine as independently callable 
functions.


> I'm still not convinced that it's as useful as you say. Compare these
> append-and-return functions:
>
> def build1(value, lst=None):
> if lst is None: lst = []
[...]
> In which of them can you introspect the []?

"Here are lots of ways to solve a problem that don't let you test or 
introspect part of your code. Therefore we shouldn't add a feature that 
will let us more easily test and introspect that part of the code."

Yes Chris, I know that emulated late-bound defaults are currently 
effectively invisible at runtime (short of byte-code hacking). That 
weakness of the status quo is why you have written this PEP.

That invisibility is not a feature we should duplicate in late-bound 
defaults, but an argument for introducing defaults that overcome that 
weakness.

Right now, your PEP adds a new feature that gives us *zero* new 
functionality. There is nothing your PEP allows us to do that we cannot 
already do. It adds no new functionality. It's just syntactic sugar for 
"if arg is missing: return expression". You compile that code (or 
something very close to it) into the body of the function.

The only wins are (1) when people stumble into the "mutable default" 
gotcha, it is easy to tell them how to fix it (but not much easier than 
the status quo) and (2) a small increase in clarity, since we will be 
able to write the default expression directly in the signature instead 
of hiding behind a sentinel.

That's not nothing, but 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Steven D'Aprano
On Wed, Dec 01, 2021 at 12:26:33PM +, Matt del Valle wrote:

> Steven gave the following example of a function signature that would be
> difficult to visually parse if this proposal and arrow lambdas were
> accepted:
> 
> def process(func:List->int=>xs=>expression)->int:
> 
> And while I agree that it does sort of stop you in your tracks when you see
> this, I think there are a couple of reasons why this is not as big of a
> problem as it appears.

I totally agree with you that, for even moderately experienced 
Pythonistas, it is possible to parse that. It's not literally ambiguous 
syntax that cannot be resolved. I am confident that the parser will be 
able to work it out just fine :-)

I care more about the poor reader who may not be a moderately 
experienced Pythonista, and will be trying to work out why there are two 
different arrow symbols with four different meanings:

* function return annotation
* typing.Callable type annotation
* lambda alternative syntax
* late-bound defaults

I'm sure that people will learn the many uses of the arrow symbols. 
After all, people learn Perl and APL :-) Closer to home, we also learn 
all the many different uses of the star symbol `*`.

Yes, spaces will help the reader *parse* the pieces of the function 
signature. But spaces doesn't help the reader decipher and remember the 
different meanings of the arrows. Also the use of extra spaces goes 
against the usual style guides that we *don't* use spaces between the 
colon and the annotation, or the equals sign and the default.

For the sake of discussion, I've been using Chris' arrow symbol, but 
that doesn't mean I've warmed to it. Aside from the other issues, it is 
the wrong way around:

parameter => expression

implies moving the parameter into the expression, which is the 
wrong way around. The expression moves into the parameter.

E.g. in R, you can write assignment with an equals sign, or an arrow, 
but the arrow points from the value to the variable:

> x <- 1 
> 2 -> y
> c(x, y) 
[1] 1 2

I've never seen a language or pseudo-code that does assignment with the 
arrow pointing from the variable to the value. Does anyone know of any?



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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 1:48 AM <2qdxy4rzwzuui...@potatochowder.com> wrote:
>
> On 2021-12-05 at 20:30:53 +1100,
> Chris Angelico  wrote:
>
> > On Sun, Dec 5, 2021 at 5:41 PM <2qdxy4rzwzuui...@potatochowder.com> wrote:
> > > Also FWIW, I still think that if you're doing (b) or (c), then you're
> > > *not* doing default values anymore, you're moving pieces of the logic or
> > > the design into the wrong place.  One example of (b) goes something like
> > > this:
> > >
> > > def write_to_log(event, time=>current_time()):
> > > actually_write_to_log(event, time)
> >
> > Very very common use-case for that:
> >
> > https://pyauth.github.io/pyotp/#time-based-otps
>
> I agree.  *Not* conflating timestamps and event IDs is a good thing!
> APIs and libraries like that are making my point:  the very notion of
> "overriding the current time" is a bad one.  The notion of "defaulting
> to the current time" might be okay, in some systems, until it isn't.

Time-based OTPs are using timestamps. That's what they do. Defaulting
to the current time is *precisely* how most 2FA systems work. Being
able to override the time is useful primarily for testing. So for the
TOTP case, I would say that "timestamp=>time.time()" is the perfect
way to spell it.

> > The vast majority of calls are going to leave the time parameter at
> > the default. (The one I linked to has separate "at" and "now"
> > functions, but combining them makes very good sense.)
>
> I disagree.  Combining/conflating the time an event occurred and the
> time it's actually logged doesn't make sense at all.  Or maybe I've
> spent too much time rummaging through logs from concurrent and parallel
> systems.
>
> Oh, wait, we're veering off topic, but you like you said, this is Python
> Ideas!  ;-)

I don't know why you'd have something in a logger that lets you
configure the time, but my guess would be that it's the same thing:
you can unit-test the logger with consistent inputs. For instance:

def format_log_line(event, time=>current_time(), host=>get_host()):
return ...

# shorthand, obv you'd be using a proper testing framework
assert format_log_line({...}, time=1638717131, host="example") == "..."

TBH, I think that defaulting to "event happened right now" is about as
good a default as you'll ever get. In some situations you'll know when
the event happened... but honestly, I'd rather know when the log line
happened too. So if I have an event with an inbuilt timestamp, I'll
incorporate that into the *body* of the log line, and still have the
logger add its own timestamp.

But maybe I've spent too much time rummaging through logs from buggy systems.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Mon, Dec 6, 2021 at 1:45 AM Steven D'Aprano  wrote:
>
> On Sat, Dec 04, 2021 at 06:11:08PM +, Barry Scott wrote:
>
> > There are many possible implementation of the late bound idea that
> > could create an object/default expression. But is it reasonable to
> > bother with that added complexity/maintenance burden for a first
> > implementation.
>
> Chris wants to throw the late-bound defaults into the body of the
> function because that's what we are currently forced to do to emulate
> late-bound defaults. But we are designing the feature from scratch, and
> we shouldn't be bound by the limitations of the existing idiom.

Not quite true. I want to have them syntactically as part of the body
of the function, and semantically as part of the function call. As a
function begins executing, a ton of stuff happens, including
allocating arguments to parameters, and providing default values for
optional parameters that weren't passed. All I want to change is the
way that defaults can be provided.

Tell me, what's the first bytecode instruction in the function g here?

def f(x):
print(x)
return lambda: x

In current CPython, it's not "LOAD_GLOBAL print". It's "MAKE_CELL x".
Conceptually, that's part of the framework of setting up the function
- setting up its local variables, providing a place for nonlocals. But
it's a bytecode at the start of the function's code object. (I'm not
sure when that became a bytecode instruction. It wasn't one in Python
2.7.) CPython bytecode is an implementation detail, and the fact that
there's bytecode to do this or that is not part of the language
definition.

> Encapsulation is good. Putting late-bound expressions in their own
> function so that they can be tested is a good thing, not a problem to be
> avoided. Most of us have, from time to time, already moved the
> late bound default into its own function just to make it easy to test in
> isolation:
>
> def func(arg=None):
> if arg is None:
> arg = _implementation()
> # and now handle arg
>
> With my strategy, we get that isolation for almost for free. There is no
> extra effort needed on the programmer's side, no new name or top-level
> function needed.

And if you want an _implementation function for external testing,
you're still welcome to do that.

def func(arg=>_implementation()):
...

No magic, just perfectly normal coding practices. If something's
important enough to test separately, refactor it into a private
function so you can call it. Why should this happen automatically for
late-bound argument defaults? From what I can tell, the only syntactic
constructs which form separate code objects are those which need them
for namespacing purposes: class blocks, nested functions, genexps,
comprehensions. Default argument values are not separate namespaces,
so they shouldn't need dedicated stack frames, dedicated code objects,
or anything like that.

> Will people take advantage of it? Of course people won't bother if the
> default is `[]` but beyond a certain level of complexity, people will
> want to test the default expressions in isolation, to be sure that it
> does the right thing.
>

Beyond a certain level of complexity, the fact that argument defaults
are in the signature will naturally pressure people to refactor them
into their own functions. I don't think we'll see people putting
multiline argument default expressions directly into the function
header.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread 2QdxY4RzWzUUiLuE
On 2021-12-05 at 20:30:53 +1100,
Chris Angelico  wrote:

> On Sun, Dec 5, 2021 at 5:41 PM <2qdxy4rzwzuui...@potatochowder.com> wrote:
> > Also FWIW, I still think that if you're doing (b) or (c), then you're
> > *not* doing default values anymore, you're moving pieces of the logic or
> > the design into the wrong place.  One example of (b) goes something like
> > this:
> >
> > def write_to_log(event, time=>current_time()):
> > actually_write_to_log(event, time)
> 
> Very very common use-case for that:
> 
> https://pyauth.github.io/pyotp/#time-based-otps

I agree.  *Not* conflating timestamps and event IDs is a good thing!
APIs and libraries like that are making my point:  the very notion of
"overriding the current time" is a bad one.  The notion of "defaulting
to the current time" might be okay, in some systems, until it isn't.

Any feature can be abused, but I don't think we should be using bad
designs and bad APIs to justify the feature in the first place.

> The vast majority of calls are going to leave the time parameter at
> the default. (The one I linked to has separate "at" and "now"
> functions, but combining them makes very good sense.)

I disagree.  Combining/conflating the time an event occurred and the
time it's actually logged doesn't make sense at all.  Or maybe I've
spent too much time rummaging through logs from concurrent and parallel
systems.

Oh, wait, we're veering off topic, but you like you said, this is Python
Ideas!  ;-)
___
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/X4OI6OANR7WGJG4EV2KRR4SMBJUPESQL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Steven D'Aprano
On Sat, Dec 04, 2021 at 06:11:08PM +, Barry Scott wrote:

> There are many possible implementation of the late bound idea that 
> could create an object/default expression. But is it reasonable to 
> bother with that added complexity/maintenance burden for a first 
> implementation.

I don't think we can conclude that factoring out the late-bound defaults 
into their own routines is "added complexity/maintenance burden".

Usually, factoring stand-alone code into its own routines *reduces* the 
maintenance burden, it doesn't increase it. You can test chunks of code 
in isolation. You can refactor it. It is easier to analyse and 
understand.

The ability to introspect code is not a "burden", it is a feature that 
reduces the difficulty of testing and maintaining code.

That's why we have functions in the first place, instead of having one 
giant ball of mud.

https://exceptionnotfound.net/big-ball-of-mud-the-daily-software-anti-pattern/

Chris wants to throw the late-bound defaults into the body of the 
function because that's what we are currently forced to do to emulate 
late-bound defaults. But we are designing the feature from scratch, and 
we shouldn't be bound by the limitations of the existing idiom.

Encapsulation is good. Putting late-bound expressions in their own 
function so that they can be tested is a good thing, not a problem to be 
avoided. Most of us have, from time to time, already moved the 
late bound default into its own function just to make it easy to test in 
isolation:

def func(arg=None):
if arg is None:
arg = _implementation()
# and now handle arg

With my strategy, we get that isolation for almost for free. There is no 
extra effort needed on the programmer's side, no new name or top-level 
function needed.

Will people take advantage of it? Of course people won't bother if the 
default is `[]` but beyond a certain level of complexity, people will 
want to test the default expressions in isolation, to be sure that it 
does the right thing.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Sun, Dec 5, 2021 at 9:58 PM Barry Scott  wrote:
 >> def inner(timestamp=>time.time()):
> >if timestamp is None: timestamp = time.time()
>
>
> And, obviously, if you end up needing the write the explicit check for None 
> there is no
> advantage to using late bound default.

Hmm, I wouldn't say NO advantage - it still puts the primary and
meaningful default in the signature, but then has a special case for
backward compatibility, or for that one caller where it makes sense,
or whatever. But yes, far less advantage when you actually have None
as part of your API. The main point of late-bound defaults is to
remove None from the API.

> Yes that's a good point. Use the *kwargs style to pass down stuff.

That's normally the recommendation anyway. It's safe against
additional parameters being added, it's safe against the defaults
changing, it clearly says "this passes on its arguments unchanged";
the only problem is that the help for the function doesn't adequately
show what parameters it can actually accept. And that's a fundamental
problem - look at these docs:

https://docs.python.org/3/library/subprocess.html#subprocess.run

"""The arguments shown above are merely the most common ones,
described below in Frequently Used Arguments (hence the use of
keyword-only notation in the abbreviated signature)."""

The docs aren't restricted to what can be implemented in an actual
function signature, yet it's still most effective to just toss in
"**other_popen_kwargs" at the end.

(That said, though: it would be rather nice to be able to do algebra
with function signatures. For instance, you could say "my signature is
that function's kwargs plus frobnosticate=42" or "my signature is that
function's kwargs minus stdin". But that's a topic for another thread
or another day.)

> > None is most assuredly not going to trigger a late-bound default.
>
> Are you state that this is because in most of the cases where I might think 
> that I need this behaviour there are better patterns to use like *kwargs?
> Is that worth stating in the PEP in the rejected ideas?

I don't think so, because None doesn't mean "omit this argument". It
is a perfectly valid value. There's also no need to say that object()
won't trigger late-bound defaults, or 0, or anything else. The only
way to cause a default argument to be evaluated is to not pass the
argument - as is already the case.

> > Python is not JavaScript :)
>
> Thank your choice of deity for that!

Yeah :) I say this because, in JavaScript, there is fundamentally no
difference between passing the special value 'undefined' (kinda like
None, although there's also null as a separate value) and not passing
the argument at all, which means that...

function foo(x="hello") {console.log("x is " + x);}
foo(undefined);
foo(foo.any_unknown_attr);

will print "x is hello" twice. I don't want that :) And that's why
there is, by definition, no value that will cause a function to think
that an argument wasn't passed.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Barry Scott


> On 4 Dec 2021, at 21:21, Chris Angelico  wrote:
> 
> On Sun, Dec 5, 2021 at 5:29 AM Barry Scott  > wrote:
>> 
>> 
>> 
>>> On 1 Dec 2021, at 06:16, Chris Angelico  wrote:
>>> 
>>> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
>>> with some additional information about the reference implementation,
>>> and some clarifications elsewhere.
>> 
>> (I suspect that there was a reply that I should be replying to but, cannot 
>> find one appropriate)
>> 
>> I have a lot of code that exploits the fact that passing an explicit None 
>> will cause the early bound default idiom to set the default for me.
>> 
>> def inner(timestamp=None):
>>if timestamp is None:
>>timestamp = time.time()
>>do_stuff...
>> 
>> def outer(timestamp=None):
>>inner(timestamp=timestamp)
>> 
>> outer can in an idiomatic way have inner default timestamp and not have to 
>> know what that means.
> 
> If you need outer() to be able to have a value that means "use the
> default", then there are three options:
> 
> 1) Don't pass timestamp at all. In simple cases where it will only and
> always specify the default, this is fine.
> 2) Define a sentinel that is indeed part of your API.
> 3) Use *args or **kwargs to choose whether to pass it or not (best if
> there are multiple of them).
> 
> You can continue to use the existing system of "if none, do this", or
> you can flip it around and have the sentinel as a special token within
> your code:
> 
> def inner(timestamp=>time.time()):
>if timestamp is None: timestamp = time.time()

And, obviously, if you end up needing the write the explicit check for None 
there is no
advantage to using late bound default.

> 
> Depends on how important this feature is outside of your own helper
> functions. (I would probably not do this for None specifically - if
> it's purely internal, I'm more likely to use a dedicated local
> sentinel object.)
> 
> But as soon as there are two or three arguments that "might have to be
> passed, might not", it's far more readable to use kwargs to pass just
> the ones you want.
> 
> def outer(**kwargs):
>inner(**kwargs)
> 
> That way, if something changes in inner(), you don't have to worry
> about breaking your caller's API.

Yes that's a good point. Use the *kwargs style to pass down stuff.

> 
>> With late bound I cannot do this without more complex pattern of building an 
>> arg list.
>> 
>> What if passing None still worked? I know the argument that there are more 
>> sentinels then None.
>> 
>> def inner(timestamp=>time.time())
>>do_stuff...
>> 
>> def outer(timestamp=None):
>>inner(timestamp=timestamp)
>> 
>> The code in inner that decides to when to allow the default could check for 
>> timestamp being
>> missing or arg present and None.
>> 
>> Would the lack of support for other sentinels out weight the simple way to 
>> get the default applied?
>> 
> 
> None is most assuredly not going to trigger a late-bound default.

Are you state that this is because in most of the cases where I might think 
that I need this behaviour there are better patterns to use like *kwargs?
Is that worth stating in the PEP in the rejected ideas?

> Python is not JavaScript :)

Thank your choice of deity for that!

Barry

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Stephen J. Turnbull
Chris Angelico writes:
 > On Sun, Dec 5, 2021 at 3:08 PM Stephen J. Turnbull
 >  wrote:

 > > This one is Worth Doing Right the first time, I think.  And IMO David
 > > Mertz is right: doing it right means a more general deferred-evaluation
 > > object (not to be confused with Deferreds that need to be queried
 > > about their value).
 > 
 > If you think that deferred evaluation objects are the right way to do
 > it, then write up a proposal to compete with PEP 671.

That's not your call, I'm afraid.  "Keep the status quo" is always a
viable option, regardless of other options.  And other things equal,
it's the preferred option.

 > In my opinion, it is a completely independent idea,

You're welcome to your opinion, of course.  But if you want to claim
that's a reason for implementing your proposal, you need to support
it.  You also need to explain why the additional potential complexity
of a third kind of default argument (evaluated at definition,
evaluated during call, evaluated when referenced) isn't a big problem.

 > which is not a complete replacement for late-bound defaults;

Why not?  If we have such objects, we could simply specify that in the
case where such an object is specified as a function parameter
default, it is evaluated in the same environment as your late-bound
defaults.  So we can have your schsemantics if that's what we want.

On the other hand, it might turn out that 90% of the time, it doesn't
matter if it's evaluated as part of the calling process, 9% of the
time the natural place to evaluate it is at the point of first use,
and 1% of the time it should be evaluated before the function body
proper is entered.  In that case the late-bound default would be of
some utility, but is it worth it?  David's "infinitesimal utility"
argument seems likely to apply.

What else would such a deferred-evaluation object be unable to do that
your late-bound default can do?

 > we could continue to have neither.

That's where I am.  More than any of these issues, the lack of a well-
defined, properly introspectable object bothers me.  In 2021, we
should provide that.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2021-12-05 Thread Chris Angelico
On Sun, Dec 5, 2021 at 5:41 PM <2qdxy4rzwzuui...@potatochowder.com> wrote:
> Also FWIW, I still think that if you're doing (b) or (c), then you're
> *not* doing default values anymore, you're moving pieces of the logic or
> the design into the wrong place.  One example of (b) goes something like
> this:
>
> def write_to_log(event, time=>current_time()):
> actually_write_to_log(event, time)

Very very common use-case for that:

https://pyauth.github.io/pyotp/#time-based-otps

The vast majority of calls are going to leave the time parameter at
the default. (The one I linked to has separate "at" and "now"
functions, but combining them makes very good sense.)

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