[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
It’s 2 options: a) It is a special constant - the only one with such property. Then it would be used solely for this purpose. I don’t think you can prevent someone from using it for something else. But I don’t think this case of misusage is a big exception to the way things are. As this would be only such constant, it then should be used only for this purpose. Standard sentinels would be used for everything else and None could be left for cross-language cases, such as json null value and similar. But as of now, it is not possible to do what I am referring to with either sentinels or None. The standard is to override default such as None with itself, witch means ‘NotProvided', but it actually is. Then that value is checked within the function’s body and if it is ’NotProvided’, then default is set. I appreciate that None value is singleton and technically it is the same one, but special value is useful if one was to have a more complex default argument and wanted to enforce it from outside, while retaining ability to specify it as well. It is simply cleaner than what is being done now. And without this PEP, I don’t think there would be a big case for it, but with this PEP, it seems more compelling as it seems to encourage more complex defaults. So no, I don’t think it is likely that another special value would be needed. All the other “special values” can be handled with sentinels. If this case is not special enough, then (b) could work. b) Property of a callable to specify an object which is treated in such manner as special constant in (a) or a decorator which emulates such behaviour. This might be even better approach as long as it is performant and reliable. Decorator could be a good option, but that depends on how performant it is. If it’s the same as e.g. `getcallargs` then, at least to me, not a very attractive option. But I think there might be case for special value as well. But again, only my opinion, I don’t really have an issue with the way things currently are with function arguments. Just answered questionnaire regarding this PEP and this is my opinion. —— I am more excited about deferred-eval, which if was implemented with neat syntax, would improve things for me in many different places in one go and from what I have seen would benefit many different areas and provide more neat solutions for several cases that came to this group & fairly elegant (although maybe not as pythonic) ones for several PEPs that were deferred or rejected. DG > On 23 Jul 2023, at 14:40, Richard Damon wrote: > > I think the question is, how is that fundamentally different than the value > "None". Once you create this "special value", some function will decide to > make it have a meaning as a passed in value, and then need a DIFFERENT > "special value" as a default. > > On 7/23/23 1:13 AM, Dom Grigonis wrote: >> Or maybe you are not listening to what I am saying. >> >> It would only take effect for arguments, which have default value. >> >> So. >> dict().__setitem__(key, NotGiven) >> type(NotGiven) >> Exception(NotGiven) >> getattr(NotGiven, name) >> >> Ok, maybe there are some crucial functions, which have argument defaults. >> But again, there is another solution then, implement efficient decorator in >> standard library, maybe as part of sentinels, maybe as part of your PEP, >> maybe separately. >> >> I never said that it isn’t hard to write low-level python code. I will do >> that when the time is right for me. And I am not claiming that it is >> possible. If you read my language, all of my doubts are clearly expressed. >> You just seem to read everything as black and white even when it is not so. >> >> However, such statements are in no way valid arguments in such discussion. >> If my idea is not optimal, not necessary, no-one needs it or any other valid >> responses, why it is not a good one - I can accept it. >> But commenting that “it makes no sense” without properly explaining to me >> why after giving it some thought - it’s not fair. >> >> Also, if you looked at things from a bit more positive perspective, maybe >> you could come up with some nice new ways how it could be done. Maybe not >> exactly what I am proposing, but some alternative, which would make it work. >> Most likely something much better than I am proposing. >> >> After all, I am trying to see how your PEP can be improved, because if it >> could be used in all cases, where None can be, then at least to me, it would >> be a no-brainer to use it instead and to adapt it as best practice. >> >> DG >> >>> On 23 Jul 2023, at 07:35, Chris Angelico wrote: >>> >>> On Sun, 23 Jul 2023 at 14:08, Dom Grigonis wrote: IT IS AN OBJECT. Never said otherwise. >>> One that you can't do any of the operations I described. There is no >>> way to use it as an object. >>> `inspect.getcallargs` can seemingly be modified for such behaviour. I just wrote a decorator, which does
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I think the question is, how is that fundamentally different than the value "None". Once you create this "special value", some function will decide to make it have a meaning as a passed in value, and then need a DIFFERENT "special value" as a default. On 7/23/23 1:13 AM, Dom Grigonis wrote: Or maybe you are not listening to what I am saying. It would only take effect for arguments, which have default value. So. dict().__setitem__(key, NotGiven) type(NotGiven) Exception(NotGiven) getattr(NotGiven, name) Ok, maybe there are some crucial functions, which have argument defaults. But again, there is another solution then, implement efficient decorator in standard library, maybe as part of sentinels, maybe as part of your PEP, maybe separately. I never said that it isn’t hard to write low-level python code. I will do that when the time is right for me. And I am not claiming that it is possible. If you read my language, all of my doubts are clearly expressed. You just seem to read everything as black and white even when it is not so. However, such statements are in no way valid arguments in such discussion. If my idea is not optimal, not necessary, no-one needs it or any other valid responses, why it is not a good one - I can accept it. But commenting that “it makes no sense” without properly explaining to me why after giving it some thought - it’s not fair. Also, if you looked at things from a bit more positive perspective, maybe you could come up with some nice new ways how it could be done. Maybe not exactly what I am proposing, but some alternative, which would make it work. Most likely something much better than I am proposing. After all, I am trying to see how your PEP can be improved, because if it could be used in all cases, where None can be, then at least to me, it would be a no-brainer to use it instead and to adapt it as best practice. DG On 23 Jul 2023, at 07:35, Chris Angelico wrote: On Sun, 23 Jul 2023 at 14:08, Dom Grigonis wrote: IT IS AN OBJECT. Never said otherwise. One that you can't do any of the operations I described. There is no way to use it as an object. `inspect.getcallargs` can seemingly be modified for such behaviour. I just wrote a decorator, which does what I proposed using `inspect` module for a chosen sentinel value. The issue is that it would be a bottleneck if used on any callable, which is continuously used. `inspect.getcallargs`, `signature`, `getfullargspec` are very expensive. If that can be done, theoretically it should be able to be done at lower level as well. After all, behaviour of it should be modelled after what is happening at the function call. Since you clearly are not listening to the discussion, I will leave you with one final recommendation: Write some code. Don't just claim that it's possible; write actual code that makes it happen. You will discover exactly how hard it is. If I am wrong, you will be able to PROVE that I am wrong, instead of merely claiming it. ChrisA -- Richard Damon ___ 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/JEIZYDJGK3RDW77FNZX5TZUP47JJT4XW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Or maybe you are not listening to what I am saying. It would only take effect for arguments, which have default value. So. dict().__setitem__(key, NotGiven) type(NotGiven) Exception(NotGiven) getattr(NotGiven, name) Ok, maybe there are some crucial functions, which have argument defaults. But again, there is another solution then, implement efficient decorator in standard library, maybe as part of sentinels, maybe as part of your PEP, maybe separately. I never said that it isn’t hard to write low-level python code. I will do that when the time is right for me. And I am not claiming that it is possible. If you read my language, all of my doubts are clearly expressed. You just seem to read everything as black and white even when it is not so. However, such statements are in no way valid arguments in such discussion. If my idea is not optimal, not necessary, no-one needs it or any other valid responses, why it is not a good one - I can accept it. But commenting that “it makes no sense” without properly explaining to me why after giving it some thought - it’s not fair. Also, if you looked at things from a bit more positive perspective, maybe you could come up with some nice new ways how it could be done. Maybe not exactly what I am proposing, but some alternative, which would make it work. Most likely something much better than I am proposing. After all, I am trying to see how your PEP can be improved, because if it could be used in all cases, where None can be, then at least to me, it would be a no-brainer to use it instead and to adapt it as best practice. DG > On 23 Jul 2023, at 07:35, Chris Angelico wrote: > > On Sun, 23 Jul 2023 at 14:08, Dom Grigonis wrote: >> >> IT IS AN OBJECT. Never said otherwise. > > One that you can't do any of the operations I described. There is no > way to use it as an object. > >> `inspect.getcallargs` can seemingly be modified for such behaviour. I just >> wrote a decorator, which does what I proposed using `inspect` module for a >> chosen sentinel value. The issue is that it would be a bottleneck if used on >> any callable, which is continuously used. `inspect.getcallargs`, >> `signature`, `getfullargspec` are very expensive. >> >> If that can be done, theoretically it should be able to be done at lower >> level as well. After all, behaviour of it should be modelled after what is >> happening at the function call. >> > > Since you clearly are not listening to the discussion, I will leave > you with one final recommendation: Write some code. Don't just claim > that it's possible; write actual code that makes it happen. You will > discover exactly how hard it is. If I am wrong, you will be able to > PROVE that I am wrong, instead of merely claiming it. > > 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/TPY2JHOBXUQIRNRYUUBUX46Y3HS4GQVK/ > 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/RTXRKZWWTRPGYHQTIRNGB57RMRFGWDQR/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, 23 Jul 2023 at 14:08, Dom Grigonis wrote: > > IT IS AN OBJECT. Never said otherwise. One that you can't do any of the operations I described. There is no way to use it as an object. > `inspect.getcallargs` can seemingly be modified for such behaviour. I just > wrote a decorator, which does what I proposed using `inspect` module for a > chosen sentinel value. The issue is that it would be a bottleneck if used on > any callable, which is continuously used. `inspect.getcallargs`, `signature`, > `getfullargspec` are very expensive. > > If that can be done, theoretically it should be able to be done at lower > level as well. After all, behaviour of it should be modelled after what is > happening at the function call. > Since you clearly are not listening to the discussion, I will leave you with one final recommendation: Write some code. Don't just claim that it's possible; write actual code that makes it happen. You will discover exactly how hard it is. If I am wrong, you will be able to PROVE that I am wrong, instead of merely claiming it. 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/TPY2JHOBXUQIRNRYUUBUX46Y3HS4GQVK/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
IT IS AN OBJECT. Never said otherwise. `inspect.getcallargs` can seemingly be modified for such behaviour. I just wrote a decorator, which does what I proposed using `inspect` module for a chosen sentinel value. The issue is that it would be a bottleneck if used on any callable, which is continuously used. `inspect.getcallargs`, `signature`, `getfullargspec` are very expensive. If that can be done, theoretically it should be able to be done at lower level as well. After all, behaviour of it should be modelled after what is happening at the function call. > On 23 Jul 2023, at 06:58, Chris Angelico wrote: > > On Sun, 23 Jul 2023 at 12:20, Dom Grigonis wrote: >> >> >>> There is no way to have a value that isn't a value, in Python. The >>> concept doesn't make sense and would break all kinds of things. >>> (That's why, when a special function like __getitem__ has to be able >>> to return literally anything, it signals "nothing to return" by >>> raising an exception.) >> >> I accept that it might be difficult to implement. >> I see that it would break things at cpython. >> Will definitely break some of the stdlib. E.g. inspect stuff. >> It wouldn’t break any of the existing python code. >> So yes, might not be a minor change. >> >> Could it be done nicely and easily by someone with relevant experience? I >> don’t know. >> >> >> But I fail to see why it doesn’t make sense - that’s a strong statement. >> >> It would be a value, just a value that is treated with exception in this >> particular case. >> There is definitely code at that level - resolving args, kwargs, dealing >> with “/" and “*” in relation to arguments provided, etc. >> >> It would take effect only on keyword arguments with defaults, if so then >> fairly contained matter. >> It could be a default of a keyword argument itself, would have a type and >> everything as any other object. >> > > Okay. You now have an object that you can't do anything with, because > it can't be a function argument. So... > > Show me how you would put this value into a dictionary. > > Show me how you would find out the type of this value. > > Show me how you would refer to this in an exception. > > Show me how you would access an attribute of this object. > > Show me how you would do ANYTHING WHATSOEVER with this object. > > It does not make sense to have an object that isn't an object. And in > Python, every value *is* an object. > > 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/CFFEGHQNQRDA7EDS4ZJBWAWDPU64OYHH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, 23 Jul 2023 at 12:20, Dom Grigonis wrote: > > > > There is no way to have a value that isn't a value, in Python. The > > concept doesn't make sense and would break all kinds of things. > > (That's why, when a special function like __getitem__ has to be able > > to return literally anything, it signals "nothing to return" by > > raising an exception.) > > I accept that it might be difficult to implement. > I see that it would break things at cpython. > Will definitely break some of the stdlib. E.g. inspect stuff. > It wouldn’t break any of the existing python code. > So yes, might not be a minor change. > > Could it be done nicely and easily by someone with relevant experience? I > don’t know. > > > But I fail to see why it doesn’t make sense - that’s a strong statement. > > It would be a value, just a value that is treated with exception in this > particular case. > There is definitely code at that level - resolving args, kwargs, dealing with > “/" and “*” in relation to arguments provided, etc. > > It would take effect only on keyword arguments with defaults, if so then > fairly contained matter. > It could be a default of a keyword argument itself, would have a type and > everything as any other object. > Okay. You now have an object that you can't do anything with, because it can't be a function argument. So... Show me how you would put this value into a dictionary. Show me how you would find out the type of this value. Show me how you would refer to this in an exception. Show me how you would access an attribute of this object. Show me how you would do ANYTHING WHATSOEVER with this object. It does not make sense to have an object that isn't an object. And in Python, every value *is* an object. 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/AHM6KHYJRFPLY3QUWV6MNCZ33BWSNR3Q/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
> There is no way to have a value that isn't a value, in Python. The > concept doesn't make sense and would break all kinds of things. > (That's why, when a special function like __getitem__ has to be able > to return literally anything, it signals "nothing to return" by > raising an exception.) I accept that it might be difficult to implement. I see that it would break things at cpython. Will definitely break some of the stdlib. E.g. inspect stuff. It wouldn’t break any of the existing python code. So yes, might not be a minor change. Could it be done nicely and easily by someone with relevant experience? I don’t know. But I fail to see why it doesn’t make sense - that’s a strong statement. It would be a value, just a value that is treated with exception in this particular case. There is definitely code at that level - resolving args, kwargs, dealing with “/" and “*” in relation to arguments provided, etc. It would take effect only on keyword arguments with defaults, if so then fairly contained matter. It could be a default of a keyword argument itself, would have a type and everything as any other object. ___ 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/YN3QPKPCN2HSTARQNXXHXZWJTH3AA5RI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, 23 Jul 2023 at 09:15, Dom Grigonis wrote: > This works ok: > > ``` > def foo(bar=None): > if bar is None: > bar = A() > > class A: > pass > ``` > > If PEP is aiming to replace the latter example, then it would be great if it > kept all of its advantages. I.e. not having to change the definition order in > the module, which could be preferred as it is for other reasons. > Well, yes, it would work, but I still wouldn't recommend it. This is confusing to read. But since the default would be evaluated at call time, it would behave exactly as you describe. > And also to come back to my previous notice that there is no way to enforce > the default in case of function chain with cascading arguments. You said it > is a known limitation. Is there no easy & sensible approach to not have it? > E.g.: > > a) Any object which has certain dunder attribute, which evaluates to True? > b) NotGiven sentinel value which does exactly that. > c) A special constant, which, if present, at lower level makes things behave > the same way as the argument wasn’t provided at all. Such constant could be > very useful outside the scope of this PEP as well. Could be a great place to > introduce such constant? And to me it seems it could be a well justified one, > given it actually is special and does not fall under umbrella of generic > sentinel values. > > It would be great if it was to retain all the benefits of the latter example. > Then (at least from my POV) this PEP would be an excellent addition, and I am > most likely be using it now if it existed. > There is no way to have a value that isn't a value, in Python. The concept doesn't make sense and would break all kinds of things. (That's why, when a special function like __getitem__ has to be able to return literally anything, it signals "nothing to return" by raising an exception.) The only way to not pass an argument in Python is to not pass it. That means, at best, something like *a or **kw, where the sequence/dict either has something or doesn't, depending on whether you want to pass the argument. None of this is changed by PEP 671 and I don't think there's a lot of point trying to, as it would only cause more problems elsewhere. 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/34HFL6N6FMEIEHB5A22BBBXBAUIXXUBP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
1. Not if it is exactly as described in PEP. 2. No. 3. - 4. Couple of points here. One check and one orthogonal idea, which would make this PEP very attractive to me. I would definitely like use this functionality if both of below points were satisfied/achievable. If any of those weren't satisfied I might just default to current syntax as I like to have a default pattern, which I know is flexible enough to cover most if not all the cases that I encounter. Currently, I manage this particular area (which your PEP is concerned with) with `None` and `unittest.Sentinel` defaults and deal with them in function's body. A. Currently, if I write: ``` def foo(bar=A()): pass class A: pass ``` I get an error. That is why having `bar=None` is advantageous. This works ok: ``` def foo(bar=None): if bar is None: bar = A() class A: pass ``` If PEP is aiming to replace the latter example, then it would be great if it kept all of its advantages. I.e. not having to change the definition order in the module, which could be preferred as it is for other reasons. My best guess is that it works the same as the latter example, (given the expression can contain other arguments, which are not there yet) but just wanted to double check. B. And also to come back to my previous notice that there is no way to enforce the default in case of function chain with cascading arguments. You said it is a known limitation. Is there no easy & sensible approach to not have it? E.g.: a) Any object which has certain dunder attribute, which evaluates to True? b) NotGiven sentinel value which does exactly that. c) A special constant, which, if present, at lower level makes things behave the same way as the argument wasn’t provided at all. Such constant could be very useful outside the scope of this PEP as well. Could be a great place to introduce such constant? And to me it seems it could be a well justified one, given it actually is special and does not fall under umbrella of generic sentinel values. It would be great if it was to retain all the benefits of the latter example. Then (at least from my POV) this PEP would be an excellent addition, and I am most likely be using it now if it existed. Regards, DG ___ 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/7DCPF624EEATZ5IRCSCHDIXDTCT2WYB3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 29 Apr 2023 at 23:01, wrote: > > Ad 4) Wouldn't "<=" be a little more logical than "=>"? The perceived > direction of the "flow" of the default value is exactly opposite, i.e., the > default value is always evaluated and then put *into* the argument. > Using arrows to represent information flow has been done, for example in APL and R, but it's generally not been a significant benefit. C++ uses flow operators in a delightfully cute way that gets old after about the second time you actually use it. (Python has done similarly cute things with certain operators, with mixed results. I think Pathlib has been quite successful, but there are others that are less so.) Flow direction simply isn't a valuable-enough piece of information to be worth reusing an existing operator and thus risking ambiguity. 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/G7ZZ3KBI44PAA26O36JXAIQNPCHBNYAT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Ad 4) Wouldn't "<=" be a little more logical than "=>"? The perceived direction of the "flow" of the default value is exactly opposite, i.e., the default value is always evaluated and then put *into* the argument. For example: def bisect_right(a, x, lo=0, hi<=len(a), *, key=None): ___ 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/WBRQJB6YCNEFGOKBXGGL6WX6M66LCRAE/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 26 Dec 2022 at 10:02, wrote: > > I didn't realize def foo(x, y=[]) had this strange artifact but it totally > makes sense, TIL. I did not get the right idea reading the PEP though, since > currently the motivation reads: > > > Optional function arguments, if omitted, often have some sort of logical > > default value. When this value depends on other arguments, or needs to be > > reevaluated each function call, there is currently no clean way to state > > this in the function header. > > and I kinda glossed over the second use-case. I feel like more emphasis can > be added since that part is what necessitates the new syntax. > > I do think that being able to reference other arguments is very useful in > it's own right and would go a long way in helping to solve the None check > problem brought up in PEP 505 even more cleanly. Yeah, they're both useful features, and both handled by the simple rule of "evaluate late-bound defaults in the context of the function body". 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/5A5UGJDLHW66VJXWUE4S6TSFLMFZIIDC/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I didn't realize def foo(x, y=[]) had this strange artifact but it totally makes sense, TIL. I did not get the right idea reading the PEP though, since currently the motivation reads: > Optional function arguments, if omitted, often have some sort of logical > default value. When this value depends on other arguments, or needs to be > reevaluated each function call, there is currently no clean way to state this > in the function header. and I kinda glossed over the second use-case. I feel like more emphasis can be added since that part is what necessitates the new syntax. I do think that being able to reference other arguments is very useful in it's own right and would go a long way in helping to solve the None check problem brought up in PEP 505 even more cleanly. ___ 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/D4DP4UB7LPYPBNPTXIZDRVD6NOPMGPQP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 26 Dec 2022 at 04:53, Steven D'Aprano wrote: > > On Sat, Dec 24, 2022 at 11:34:19AM -0500, Shironeko wrote: > > > > Is the => syntax needed? as far as I can think of, the only time where > > late evaluation is needed is when the expression references the other > > arguments. > > You are missing the most common case, the motivating case, for > late-bound defaults: mutable defaults. > > def spam(x, y=>[]): > pass Exactly - this is the most important reason. So the true reason for the => syntax is: in order to gain late-bound defaults, we have to distinguish them from early-bound defaults (because changing ALL function default arguments to late-bound would be a massive breaking change). There's no particular reason for it to be "=>" specifically, and other syntax options have been considered, but it does need to be something other than "=". > The ability for default values to refer to other parameters is a Nice To > Have, not a Must Have. It has been a very long time since I have read > the PEP, and I don't remember whether it reviews other languages to see > what functionality they provide for defaults, but I don't think many > other languages allow you to set the default of one parameter to be > another parameter. JavaScript does, by nature of its extremely simplistic definition of argument defaults. function f(x=1, y=x) {console.log("--> x = ", x, ", y = ", y);} f(5) --> x = 5 , y = 5 f() --> x = 1 , y = 1 f(42, undefined) --> x = 42 , y = 42 f(undefined, 123) --> x = 1 , y = 123 Ruby does: $ irb irb(main):001:1* def f(x=1, y=x) irb(main):002:1* puts "x = #{x}, y = #{y}" irb(main):003:0> end => :f irb(main):004:0> f() x = 1, y = 1 => nil irb(main):005:0> f(123) x = 123, y = 123 => nil I suspect that, in each case, the rule is quite simple: the argument default is evaluated in the context of the function's body. Exactly the same as PEP 671 proposes. Any other languages to test? 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/CIPBJHCLGEUEVLOHPEA6WYNNCD63A7NP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, Dec 24, 2022 at 11:34:19AM -0500, Shironeko wrote: > > Is the => syntax needed? as far as I can think of, the only time where > late evaluation is needed is when the expression references the other > arguments. You are missing the most common case, the motivating case, for late-bound defaults: mutable defaults. def spam(x, y=>[]): pass Here the intention is to have y's default be a *different* list each time you call spam(x), instead of the same list each time. The ability for default values to refer to other parameters is a Nice To Have, not a Must Have. It has been a very long time since I have read the PEP, and I don't remember whether it reviews other languages to see what functionality they provide for defaults, but I don't think many other languages allow you to set the default of one parameter to be another parameter. -- 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/HS7WJGA4CROKOCVVIECEXBNKEFOBQ3LQ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Is the => syntax needed? as far as I can think of, the only time where late evaluation is needed is when the expression references the other arguments. So the rule “if the expression reference other arguments it will get evaluated at function call time” should suffice right? In effect: def foo(a, b=len(a), c=max(b, d), d=15): gets translated into def foo(a, b=None, c=None, d=15): if b is None: b = len(a) if c is None: c = max(b, d) I’m not sure if this is already brought up in previous emails, I tried my best to search for it but can’t find any reference. Also, I think the sepc should not leave any ambiguous behavior otherwise it creates subtle incompatibilities when people use different implementations. This goes for whether all other argument can be referenced or only some argument can be. Or if the use of outer scope variables should get evaluated at def time, something like foo(a, b=max(a, outer.length())) should length() be ran once or on every function call. Stuff like these create an functional effect to the user so they ought to be well defined and not implementation specific. ___ 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/ENILUNXZUIAI4OOH6XLHLFYHXOAHO4JY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, 21 Sept 2022 at 11:27, Michael Scott Cuthbert wrote: > > [Michael Cuthbert:] > > > I'm rather surprised though that the typing advantages of the pep have > > > not been emphasized enough. > > [Chris Angelico] > > That would be because I personally don't use that kind of strict > > typing, so it's not something I'm really qualified to talk about. > > Would you like to write up a paragraph or two about it? I could > > incorporate it verbatim, if you like. > > Sure! Cool, thanks for writing that up. > When the editor moves to a typed version, something like this would seem > reasonable: "Editor" could mean a person or a program. Which do you mean? I want to guess you mean the person making the edit, but it's not quite clear. Otherwise, looks good. 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/GU7O3QAGDXH5MT5RMF2GNXPKBDUJLD4Z/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
[Michael Cuthbert:] > > I'm rather surprised though that the typing advantages of the pep have not > > been emphasized enough. [Chris Angelico] > That would be because I personally don't use that kind of strict > typing, so it's not something I'm really qualified to talk about. > Would you like to write up a paragraph or two about it? I could > incorporate it verbatim, if you like. Sure! * * * Late-bound arg defaults also help with proper typing, especially for established code-bases that are incrementally adding typing to their code. For instance, take this untyped example that might take a list of musical pitches and put them in a particular order: def order_pitches(pitches=None): if pitches is None: pitches = [] ... # do reordering referencing "pitches" a lot pitches.sort(key=lambda p: (p.octave, p.name)) return pitches When the editor moves to a typed version, something like this would seem reasonable: def order_pitches(pitches: list[Pitch]|None = None) -> list[Pitch]: ... # same code as above. However, some type checkers (for instance, that of PyCharm 2022) will continue to reveal the type as "list[Pitch]|None" even after type narrowing. (Mypy will correctly type narrow in this example but not in code that checks for `if not hasattr(pitches, '__iter__')` and in many other more complex examples). In this case, authors sometimes need to resort to rewriting code with a new variable name: def order_pitches(pitches: list[Pitch]|None = None) -> list[Pitch]: non_none_pitches: list[Pitch] if pitches is None: non_none_pitches = [] else: non_none_pitches = cast(list[Pitch], pitches) ... # rest of code must be rewritten to use "non_none_pitches" The typed definition also seems to imply that "None" is an acceptable calling type for the function rather than just being a stand-in for an omitted call. A type-checker will allow `order_pitches(None)` to pass, perhaps preventing later refactoring to use a sentinel such as: def order_pitches(pitches: list[Pitch]|MISSING = MISSING) -> list[Pitch]: if pitches is MISSING: pitches = [] ... With the PEP, the process of adding typing does not impact the code, nor imply that "None" is a fine calling signature. def order_pitches(pitches: list[Pitch] => []) -> list[Pitch]: ... # pitches is always list[Pitch] and needs no narrowing pitches.sort(...) return pitches * * * It is true that the tools for automatic type-narrowing continue to get better (in looking up code that broke the type-narrowing with a "no_none..." variable, I found that 2 of 4 places I found where I had done this workaround two years ago no longer needed it for either mypy or PyCharm), but there are still numerous cases where the process of typing around a sentinel type that will be replaced by the correct type for computing still unnecessarily exist. ___ 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/3MCSLWZUQQTK6FQWTBTCQPUUTGIFKND4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 17 Sept 2022 at 09:40, Michael Scott Cuthbert wrote: > > Very late addition to these long threads -- I'm loving the proposal. I'm > rather surprised though that the typing advantages of the pep have not been > emphasized enough. That would be because I personally don't use that kind of strict typing, so it's not something I'm really qualified to talk about. Would you like to write up a paragraph or two about it? I could incorporate it verbatim, if you like. > I have a lot of code that in order to get correct typing in a strict mode > does something like this: > > ``` > def move_pitches(pitches: list[Pitch]|None = None): > non_none_pitches: list[Pitch] > if pitches is None: > non_none_pitches = [] > else: > non_none_pitches = pitches > ``` > > with the PEP, the typing becomes: > > ``` > def move_pitches(pitches: list[Pitch] => []): > ... > ``` > > and not only is the variable typed properly and more simply from the start, > but I get to use my preferred variable name throughout. > Yeah, that is definitely an advantage, without a doubt! 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/MHCXH6T7LGRRA2V2RVBJJH4ECNW34U2C/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Very late addition to these long threads -- I'm loving the proposal. I'm rather surprised though that the typing advantages of the pep have not been emphasized enough. I have a lot of code that in order to get correct typing in a strict mode does something like this: ``` def move_pitches(pitches: list[Pitch]|None = None): non_none_pitches: list[Pitch] if pitches is None: non_none_pitches = [] else: non_none_pitches = pitches ``` with the PEP, the typing becomes: ``` def move_pitches(pitches: list[Pitch] => []): ... ``` and not only is the variable typed properly and more simply from the start, but I get to use my preferred variable name throughout. Since I do about 30% of my work in TypeScript, the idea that `=>` implies that the right side will be evaluated in some way and returned is a cognitive lightening not burden. I do think that the PEP should be stricter in defining whether if an implementation chooses to do the evaluating in two passes whether normal '=' arguments to the right can or cannot be referenced by late-bound arguments. I initially read the PEP as saying that you might or might not be able to reference rightward normal arguments depending on the implementation. - Michael Scott Asato Cuthbert (music21) ___ 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/HL6U6YGJAZQGCXXB3PSFIKEU3CPHE6F2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, 27 Jul 2022 at 08:39, Stanislav Zmiev wrote: > 4) If "no" to question 1, is there some other spelling or other small > change that WOULD mean you would use it? (Some examples in the PEP.) > defer keyword that Andre proposed is a better option, in my opinion. However, > I don't like the entire idea so I would argue against that as well. Don't > take it as something bad -- it's a good idea in general but I believe that > it's a step in the wrong direction specifically for python as it is. > Except that the defer keyword *simply doesn't work* for this use-case. In my opinion, that's a bit of a downside. I posted examples of the problems in the other thread, but there were no replies. 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/SHNMO6PJLGG3ADMAG2Z5CBDK4CGBFE5X/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
1) If this feature existed in Python 3.11 exactly as described, would you use it? Definitely not. It significantly increases cognitive burden on the reader. If python didn't have pattern matching, walrus, ternary expressions, etc -- then maybe I would consider this as something harmless. But right now we are at risk of slowly turning a great language into a monstrosity. We already have a tool (an if statement) that solves this problem just as well, is a widely known pattern, and is a lot easier to read. 2) Independently: Is the syntactic distinction between "=" and "=>" a cognitive burden? Yes, but a slight one. 4) If "no" to question 1, is there some other spelling or other small change that WOULD mean you would use it? (Some examples in the PEP.) defer keyword that Andre proposed is a better option, in my opinion. However, I don't like the entire idea so I would argue against that as well. Don't take it as something bad -- it's a good idea in general but I believe that it's a step in the wrong direction specifically for python as it is. 5) Do you know how to compile CPython from source, and would you be willing to try this out? I do know how to compile it but I believe that the examples from your pep are great and paint a realistic enough picture of how it's going to feel so I'm afraid I have to refuse to test it. Sorry :) ___ 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/5EAE2GP7SZ6M5MWKVFRQFIJ3PFUCZ6ML/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 2022-06-20 22:54, Chris Angelico wrote: You are welcome to dislike the PEP on the basis that the existing language is better than it would be with this feature. I personally disagree, but that's what opinions are. But to object on the mere basis that something MIGHT, despite demonstrated evidence, be better? That is unfair and unhelpful. Again, I disagree, and I think that stance is unreasonable. There is nothing wrong with saying "Let's not do this. Instead let's wait and explore other ideas and see if we come up with something better." There is no requirement to provide any alternative proposal whatsoever --- whether vague or specific, real or potential, conceptual or concrete --- merely to justify opposing this PEP. -- 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/6OKKZLXQLWMN4VGGS2W53FMCZ76NFSA7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I will post to a different thread for my actual semi-proposal. But to answer the claim that late-bound arg defaults and late-bound everything-else are unrelated, and to start with an early version of what I'd actually want, I wrote this: https://github.com/DavidMertz/peps/blob/master/pep-.rst I could definitely use help making it better from anyone who is sympathetic with the idea of generalized deferred computation in Python. On Tue, Jun 21, 2022 at 5:12 AM Paul Moore wrote: > On Tue, 21 Jun 2022 at 10:01, Paul Moore wrote: > > > PS To be clear, my objections to the PEP aren't based on deferred > > evaluation. So I'm an impartial 3rd party on this matter. I *do* have > > problems with the PEP, so I have an interest in seeing the PEP fairly > > reflect the lack of consensus, and accurately represent the concerns > > people are raising, but I don't have a preference for any specific > > outcome in the matter of deferred evaluation. > > Thinking some more about this, my comments are pretty much what I'd be > saying if I were a sponsor for this PEP. I don't think a PEP sponsor > should be someone who doesn't agree with the PEP, otherwise I'd offer > to take on the role (assuming you need a sponsor). But please take my > comments in that vein. (And if you do ever manage to convert me to > support of the PEP, remind me of this comment and I'll be the sponsor > ;-)) > > Paul > ___ > 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/LLEEOLPQTM5INNXRIIT6UVN3TEJLQIZD/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- 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/BV4MAZPIZA33NMDH7B5W2UFXZ22ZX7AH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 10:01, Paul Moore wrote: > PS To be clear, my objections to the PEP aren't based on deferred > evaluation. So I'm an impartial 3rd party on this matter. I *do* have > problems with the PEP, so I have an interest in seeing the PEP fairly > reflect the lack of consensus, and accurately represent the concerns > people are raising, but I don't have a preference for any specific > outcome in the matter of deferred evaluation. Thinking some more about this, my comments are pretty much what I'd be saying if I were a sponsor for this PEP. I don't think a PEP sponsor should be someone who doesn't agree with the PEP, otherwise I'd offer to take on the role (assuming you need a sponsor). But please take my comments in that vein. (And if you do ever manage to convert me to support of the PEP, remind me of this comment and I'll be the sponsor ;-)) Paul ___ 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/LLEEOLPQTM5INNXRIIT6UVN3TEJLQIZD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 09:20, Chris Angelico wrote: > > On Tue, 21 Jun 2022 at 18:15, Paul Moore wrote: > > I'm not talking about a "full and detailed specification". That's > > *still* more than is needed for a valid debate (at this point). But > > what *is* needed is a more complete explanation of how deferred > > evaluation would work, and some plausible (not set in stone, just > > plausible) syntax. With that, it would be possible to write down two > > versions of the same code and judge between them. We've not yet had a > > sufficiently clear (IMO) definition of the semantics of deferred > > evaluation yet (or if we have, it's been lost in the arguments), and > > it would help a lot if someone could provide one. I'm thinking > > specifically about the rules for variable capture, scoping, > > interaction with assignment expressions in terms of introducing names, > > etc., as well as how evaluation is "triggered" and what ability there > > is to explicitly say "evaluate this now". > > > > That's what I mean by a full specification. Even without code, that > would be enough to start talking about it. But those arguing "don't go > for lazy evaluation, go for deferreds" don't seem to want to actually > push that proposal forward. > > That's why I call it vapourware. OK, so maybe if you were a little less aggressive in your replies, we could see if anyone wants to respond. But frankly, I imagine it's hard to muster up any enthusiasm for writing up the semantics unless you're willing to show some sign that you might modify the PEP as a result. I'm not talking about rewriting your PEP to be a "deferred evaluation" PEP, but simply to modify it to make it more compatible with the future that the "deferred evaluation" people imagine. On the other hand, if the "deferred evaluation" supporters genuinely have nothing to offer other than "we don't want this PEP *at all* because what we have right now is sufficient in the short term, and longer term maybe something else (deferred evaluation being the possibility we can think of right now) will provide a different solution" then that's also OK. It's just a -1 vote, and should be recorded in the PEP as such - "A number of contributors on python-ideas were against this proposal because they didn't believe it offered enough benefit over the status quo, and they preferred to wait for a more general solution such as deferred evaluation (on the basis of the Zen "never is often better than right now")". That can still go in the "rejected ideas" section, under a heading of "Do Nothing". But unless we can reduce the level of conflict here, we're never going to know which alternative the deferred evaluation supporters want, and it won't be possible to accurately represent their views in the PEP. Which is bad for them (as they'll feel ignored) and for you (as your PEP won't fairly represent the views of the people who contributed to the discussion). Paul PS To be clear, my objections to the PEP aren't based on deferred evaluation. So I'm an impartial 3rd party on this matter. I *do* have problems with the PEP, so I have an interest in seeing the PEP fairly reflect the lack of consensus, and accurately represent the concerns people are raising, but I don't have a preference for any specific outcome in the matter of deferred evaluation. ___ 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/PLQRTPEVRNU5VGVCRXDUV3ERSFX37RLF/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 18:15, Paul Moore wrote: > I'm not talking about a "full and detailed specification". That's > *still* more than is needed for a valid debate (at this point). But > what *is* needed is a more complete explanation of how deferred > evaluation would work, and some plausible (not set in stone, just > plausible) syntax. With that, it would be possible to write down two > versions of the same code and judge between them. We've not yet had a > sufficiently clear (IMO) definition of the semantics of deferred > evaluation yet (or if we have, it's been lost in the arguments), and > it would help a lot if someone could provide one. I'm thinking > specifically about the rules for variable capture, scoping, > interaction with assignment expressions in terms of introducing names, > etc., as well as how evaluation is "triggered" and what ability there > is to explicitly say "evaluate this now". > That's what I mean by a full specification. Even without code, that would be enough to start talking about it. But those arguing "don't go for lazy evaluation, go for deferreds" don't seem to want to actually push that proposal forward. That's why I call it vapourware. 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/LVQUBGE74OXAT7IVVCOQJBKE5TNPINPN/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 06:27, Chris Angelico wrote: > > Okay, here's a compromise. > > Go and write a full and detailed specification of the Python-visible > semantics of deferred evaluation objects, including how they would be > used to implement late-bound argument defaults. I'm going to ignore all the rhetoric here, as it's not helpful. I understand that you're frustrated, and that you feel like you're not getting your point across. Part of that (IMO) is *because* you're getting too frustrated, and so not explaining your point well. This is a case in point. Deferred evaluation doesn't need to be implemented to be a valid counter-proposal. Your repeated demands that someone produce an implementation are a distraction, allowing people to argue that you're wrong on that point, while ignoring the more important point. Which is that we don't really have a definition of how deferred evaluation would work. I'm not talking about a "full and detailed specification". That's *still* more than is needed for a valid debate (at this point). But what *is* needed is a more complete explanation of how deferred evaluation would work, and some plausible (not set in stone, just plausible) syntax. With that, it would be possible to write down two versions of the same code and judge between them. We've not yet had a sufficiently clear (IMO) definition of the semantics of deferred evaluation yet (or if we have, it's been lost in the arguments), and it would help a lot if someone could provide one. I'm thinking specifically about the rules for variable capture, scoping, interaction with assignment expressions in terms of introducing names, etc., as well as how evaluation is "triggered" and what ability there is to explicitly say "evaluate this now". > Go and actually do some real work on your pet feature, instead of > using the vapourware to try to shut down the one I've been working on. This is rhetoric again. Asking for more concrete examples of the proposed alternative is reasonable. Getting frustrated when they are not provided is understandable, but doesn't help. Calling the proposed alternative "vapourware" just doubles down on the uncompromising "implement it or I'll ignore you" stance. And replying with increasingly frustrated posts that end up at a point where people like me can't even work out how we'd go looking to see whether anyone *had* provided concrete examples of deferred evaluation just makes things worse. All of which could have been avoided by simply including an early argument posted here in the PEP, under rejected alternatives, with a link to the post and a statement that "this was proposed as an alternative, but there's not enough detail provided to confirm how it would replace the existing proposal". Then anyone who disagrees has a clear understanding of what you want, and how to provide it. > Once again, you're getting very very close to being killfiled. This whole discussion is close to that point for me. But believe it or not, I still have a vague hope that the proposal can be strengthened by people working together, rather than just ending up with a "this is what I think, take it or leave it" PEP. Paul ___ 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/LZJF4P77YCTX5TM7JJ4VW64JD4DDTBN2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 15:48, Brendan Barnwell wrote: > > On 2022-06-20 22:26, Chris Angelico wrote: > > Okay, here's a compromise. > > > > Go and write a full and detailed specification of the Python-visible > > semantics of deferred evaluation objects, including how they would be > > used to implement late-bound argument defaults. > > > > Go and actually do some real work on your pet feature, instead of > > using the vapourware to try to shut down the one I've been working on. > > > > Go and actually do something useful instead of just arguing that "it > > must be possible". > > I'm not the person you're replying to, but just a reminder here: there > is one alternative proposal that already has a fully functioning > implementation, namely the current behavior. Your arguments against the > deferred-evaluation proposal seem to constantly be reiterating that > there is no concrete deferred-evaluation proposal. You are right. But > your arguments also seem to be insinuating that if there is no such > proposal, then opposition to the PEP is somehow misguided, and that is > incorrect. There doesn't need to be any concrete alternative proposal > other than "leave everything as it is and wait until we think of > something better". > > It is perfectly valid to oppose your PEP even on the basis that maybe > a > deferred-evaluation proposal has a remote possibility of being better in > the future --- because it is perfectly valid to oppose your PEP even if > such a proposal has NO possibility of being better in the future. There > is no urgency or need for the behavior described in your PEP. I am fine > with the current behavior of Python in this regard. It is not necessary > to provide any alternative proposal, concrete or handwavy, to argue that > the PEP is a bad idea. I believe the PEP is a bad idea because the > current behavior of Python is actually better than what it would be if > the PEP were adopted. I believe it is better to wait until we think of > a better idea than to implement this PEP, and, if we never think of a > better idea, then never change the existing argument-default behavior of > Python. I have laid out, multiple times, how a deferred evaluation feature is completely distinct from late-bound argument defaults. So have others. Steven continues to assert that, just because it MIGHT be possible to use them in the implementation, we should stop working on this and start working on that. He would, of course, be very welcome to work on deferred evaluation himself, but he chooses to hide behind his own ignorance of C to avoid doing any such work, and then still argues that we should stop working on this because, in his opinion solely, it would be more useful to have deferred evaluation. And then he calls me a liar for saying in the PEP the same thing that I've been saying here, yet he won't even write up a full specification for deferred evaluation. You are welcome to dislike the PEP on the basis that the existing language is better than it would be with this feature. I personally disagree, but that's what opinions are. But to object on the mere basis that something MIGHT, despite demonstrated evidence, be better? That is unfair and unhelpful. 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/7SIYYEJFFQ2MW2RKFGUI3HIEKGRJ6WGF/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 2022-06-20 22:26, Chris Angelico wrote: Okay, here's a compromise. Go and write a full and detailed specification of the Python-visible semantics of deferred evaluation objects, including how they would be used to implement late-bound argument defaults. Go and actually do some real work on your pet feature, instead of using the vapourware to try to shut down the one I've been working on. Go and actually do something useful instead of just arguing that "it must be possible". I'm not the person you're replying to, but just a reminder here: there is one alternative proposal that already has a fully functioning implementation, namely the current behavior. Your arguments against the deferred-evaluation proposal seem to constantly be reiterating that there is no concrete deferred-evaluation proposal. You are right. But your arguments also seem to be insinuating that if there is no such proposal, then opposition to the PEP is somehow misguided, and that is incorrect. There doesn't need to be any concrete alternative proposal other than "leave everything as it is and wait until we think of something better". It is perfectly valid to oppose your PEP even on the basis that maybe a deferred-evaluation proposal has a remote possibility of being better in the future --- because it is perfectly valid to oppose your PEP even if such a proposal has NO possibility of being better in the future. There is no urgency or need for the behavior described in your PEP. I am fine with the current behavior of Python in this regard. It is not necessary to provide any alternative proposal, concrete or handwavy, to argue that the PEP is a bad idea. I believe the PEP is a bad idea because the current behavior of Python is actually better than what it would be if the PEP were adopted. I believe it is better to wait until we think of a better idea than to implement this PEP, and, if we never think of a better idea, then never change the existing argument-default behavior of Python. -- 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/FTC2N3APMR3YUBJYAOEIWTHRL4HXNTWX/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
wt., 21 cze 2022 o 05:20 Steven D'Aprano napisał(a): > The point is, Rob thought (and possibly still does, for all I know) that > lazy evaluation is completely orthogonal to late-bound defaults. The PEP > makes that claim too, even though it is not correct. With a couple of > tweaks that we have to do anyway, and perhaps a change of syntax (and > maybe not even that!) we can get late-bound defaults *almost* for free > if we had lazy evaluation. That depends of lazy evaluation spec, if lazy expression would ever become a thing in python, it may be defined to have syntax like `lazy ` which would be rough equivalent off `LazyObject(lambda: )` that would evaluate that lambda at most once, plus some interpreter tweaks to make LazyObject transparent to python code. so for this code (`??` replaced with different combination of early/late and not lazy/lazy) ``` x = [] def f(x, y, z ?? len(x)): x.append(y) print(z, end = ' ') x.append(0) f([1, 2, 3], 4) x.append(0) f([1, 2, 3, 4], 4) ``` I expect that for `??` = `=` I get `0 0 ` for `??` = `=>` I get `3 4 ` for `??` = `= lazy` I get `1 1` for '??' = `=> lazy` I get `4 5 ` That would be completely orthogonal. ___ 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/GZ2OCWGI67FTZGTCNHHYAXB7Y54LBTPY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 13:17, Steven D'Aprano wrote: > > On Tue, Jun 21, 2022 at 12:13:08AM +1000, Chris Angelico wrote: > > > Nice analogy. It doesn't hold up. > > > > Consider this function: > > > > def f(stuff, max=>len(stuff)): > > stuff.append(1) > > print(max) > > > > f([1,2,3]) > > > > How would you use lazy evaluation to *guarantee* the behaviour here? > > By "the behaviour" I presume you want `max` evaluated before the body of > the function is entered, rather than at its point of use. > > Same way your implementation does: ensure that the interpreter > fully evaluates `max` before entering the body of the function. YES! Which means that guess what! It's NOT the same as having a default which is a deferred evaluation object! It would be *buggy behaviour* if you set the default to be a deferred evaluation object, and the interpreter evaluated it on entering the body. > > The only way I can imagine doing it is basically the same as I'm > > doing: that late-bound argument defaults *have special syntax and > > meaning to the compiler*. If they were implemented with some sort of > > lazy evaluation object, they would need (a) access to the execution > > context, so you can't just use a function; > > Obviously you can't just compile the default expression as a function > *and do nothing else* and have late bound defaults magically appear from > nowhere. > > Comprehensions are implemented as functions. Inside comprehensions, the > walrus operator binds to the caller's scope, not the comprehension scope. > > >>> def frob(items): > ... thunk = ((w:=len(items)) for x in (None,)) > ... next(thunk) > ... return ('w' in locals(), w) > ... > >>> frob([1, 2, 3, 4, 5]) > (True, 5) > > That seems to be exactly the behaviour needed for lazy evaluation > thunks, except of course we don't need all the other goodies that > generators provide (e.g. send and throw methods). GO AND IMPLEMENT IT. I'm done arguing this. Write the code. You'll find it's a LOT more problematic than you claim. > One obvious difference is that currently if we moved that comprehension > into the function signature, it would use the `items` from the > surrounding scope (because of early binding). It has to be set up in > such a way that items comes from the correct scope too. > > If we were willing to give up fast locals, I think that the normal LEGB > lookup will do the trick. That works for locals inside classes, so I > expect it should work here too. I wouldn't want to give up fast locals. > > (b) guaranteed evaluation on function entry, > > If that's the behaviour that people prefer, sure. Functions would need > to know which parameters were: > > 1. defined with a lazy default; > 2. and not passed an argument by the caller (i.e. actually using >the default) > > and for that subset of parameters, evaluate them, before entering the > body of the function. That's kinda what you already do, isn't it? But what if you wanted the default to actually be a deferred evaluation object? BAM, buggy behaviour, according to your spec. > > (c) the ability to put it in the function header. > > Well sure. But if we have syntax for a lazily evaluated expression it > would be an expression, right? So we can put it anywhere an expression > can go. Like parameter defaults in a function header. Yes. See? You could do it as a completely separate proposal, like we've been saying. > The point is, Rob thought (and possibly still does, for all I know) that > lazy evaluation is completely orthogonal to late-bound defaults. The PEP > makes that claim too, even though it is not correct. With a couple of > tweaks that we have to do anyway, and perhaps a change of syntax (and > maybe not even that!) we can get late-bound defaults *almost* for free > if we had lazy evaluation. GO AND WRITE THE CODE. > That suggests that the amount of work to get *both* is not that much > more than the work needed to get just one. Why have a car that only > drives to the mall on Thursdays when you can get a car that can drive > anywhere, anytime, and use it to drive to the mall on Thursday as well? GO AND WRITE THE CODE. > > Please stop arguing this point. It is a false analogy and until you > > can demonstrate *with code* that there is value in doing it, it is a > > massive red herring. > > You can make further debate moot at any point by asking Python-Dev for a > sponsor for your PEP as it stands right now. If you think your PEP is > as strong as it can possibly be, you should do that. > > (You probably want to fix the broken ReST first.) > > Chris, you have been involved in the PEP process for long enough, as > both a participant of discussions and writer of PEPs, that you know damn > well that there is no requirement that all PEPs must have a working > implementation before being accepted, let alone being *considered* by > the community. > > Yes, we're all very impressed that you are a competent C programmer who > can
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 13:07, Steven D'Aprano wrote: > > On Tue, Jun 21, 2022 at 03:15:32AM +0100, Rob Cliffe wrote: > > > Why do people keep obscuring the discussion of a PEP which addresses > > Problem A by throwing in discussion of the (unrelated) Problem B? > > (Chris, and I, have stated, ad nauseam, that these *are* unrelated > > problems. > > Chris says: > > "Even if Python does later on grow a generalized lazy evaluation > feature, it will only change the *implementation* of late-bound > argument defaults, not their specification." > > So you are mistaken that they are unrelated. > *facepalm* I'm not offering you a way to put C code in your Python function defaults. However, there is a large amount of C code in the implementation of them, at least in my reference implementation. So I guess the features of late-bound defaults and C code in function defaults aren't unrelated either, and I should stop working on this and start working on that. Seriously? Are you unable to distinguish implementation from specification? What are you even doing on this mailing list? 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/WGGAMLKO2RCNBRCWR3UPDOEY4K22VAWT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, Jun 21, 2022 at 12:13:08AM +1000, Chris Angelico wrote: > Nice analogy. It doesn't hold up. > > Consider this function: > > def f(stuff, max=>len(stuff)): > stuff.append(1) > print(max) > > f([1,2,3]) > > How would you use lazy evaluation to *guarantee* the behaviour here? By "the behaviour" I presume you want `max` evaluated before the body of the function is entered, rather than at its point of use. Same way your implementation does: ensure that the interpreter fully evaluates `max` before entering the body of the function. > The only way I can imagine doing it is basically the same as I'm > doing: that late-bound argument defaults *have special syntax and > meaning to the compiler*. If they were implemented with some sort of > lazy evaluation object, they would need (a) access to the execution > context, so you can't just use a function; Obviously you can't just compile the default expression as a function *and do nothing else* and have late bound defaults magically appear from nowhere. Comprehensions are implemented as functions. Inside comprehensions, the walrus operator binds to the caller's scope, not the comprehension scope. >>> def frob(items): ... thunk = ((w:=len(items)) for x in (None,)) ... next(thunk) ... return ('w' in locals(), w) ... >>> frob([1, 2, 3, 4, 5]) (True, 5) That seems to be exactly the behaviour needed for lazy evaluation thunks, except of course we don't need all the other goodies that generators provide (e.g. send and throw methods). One obvious difference is that currently if we moved that comprehension into the function signature, it would use the `items` from the surrounding scope (because of early binding). It has to be set up in such a way that items comes from the correct scope too. If we were willing to give up fast locals, I think that the normal LEGB lookup will do the trick. That works for locals inside classes, so I expect it should work here too. > (b) guaranteed evaluation on function entry, If that's the behaviour that people prefer, sure. Functions would need to know which parameters were: 1. defined with a lazy default; 2. and not passed an argument by the caller (i.e. actually using the default) and for that subset of parameters, evaluate them, before entering the body of the function. That's kinda what you already do, isn't it? One interesting feature here is that you don't have to compile the default expressions into the body of the function. You can stick them in the code object, as distinct, introspectable thunks with a useful repr. Potentially, the only extra code that needs go inside the function body is a single byte-code to instantiate the late-bound defaults. Even that might not need to go in the function body, it could be part of the CALL_FUNCTION and CALL_FUNCTION_KW op codes (or whatever we use). > (c) the ability to put it in the function header. Well sure. But if we have syntax for a lazily evaluated expression it would be an expression, right? So we can put it anywhere an expression can go. Like parameter defaults in a function header. The point is, Rob thought (and possibly still does, for all I know) that lazy evaluation is completely orthogonal to late-bound defaults. The PEP makes that claim too, even though it is not correct. With a couple of tweaks that we have to do anyway, and perhaps a change of syntax (and maybe not even that!) we can get late-bound defaults *almost* for free if we had lazy evaluation. That suggests that the amount of work to get *both* is not that much more than the work needed to get just one. Why have a car that only drives to the mall on Thursdays when you can get a car that can drive anywhere, anytime, and use it to drive to the mall on Thursday as well? > Please stop arguing this point. It is a false analogy and until you > can demonstrate *with code* that there is value in doing it, it is a > massive red herring. You can make further debate moot at any point by asking Python-Dev for a sponsor for your PEP as it stands right now. If you think your PEP is as strong as it can possibly be, you should do that. (You probably want to fix the broken ReST first.) Chris, you have been involved in the PEP process for long enough, as both a participant of discussions and writer of PEPs, that you know damn well that there is no requirement that all PEPs must have a working implementation before being accepted, let alone being *considered* by the community. Yes, we're all very impressed that you are a competent C programmer who can write an initial implementation of your preferred design. But your repeated gate-keeping efforts to shut down debate by wrongly insisting that only a working implementation may be discussed is completely out of line, and I think you know it. Being a C programmer with a working knowledge of the CPython internals is not, and never has been, a prerequisite for
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, Jun 21, 2022 at 03:15:32AM +0100, Rob Cliffe wrote: > Why do people keep obscuring the discussion of a PEP which addresses > Problem A by throwing in discussion of the (unrelated) Problem B? > (Chris, and I, have stated, ad nauseam, that these *are* unrelated > problems. Chris says: "Even if Python does later on grow a generalized lazy evaluation feature, it will only change the *implementation* of late-bound argument defaults, not their specification." So you are mistaken that they are unrelated. Chris could end this debate (and start a whole new one!) by going to the Python-Dev mailing list and asking for a sponsor, and if he gets one, for the Steering Council to make a ruling on the PEP. He doesn't *need* consensus on Python-Ideas. (Truth is, we should not expect 100% agreement on any new feature.) But any arguments, questions and criticisms here which aren't resolved will just have to be re-hashed when the core devs and the Steering Council read the PEP. They can't be swept under the carpet. -- 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/2NAYYR4YX33KRFH5NH3RNHXXTNX2OVSS/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 18/06/2022 15:51, Stephen J. Turnbull wrote: > This raises another choice: should lazy defaults be evaluated before > entering the body of the function, or at the point where the parameter > is used? Which would be more useful? Both are potentially useful. Yes, both *ARE* potentially useful. *ABSOLUTELY*. I don't think anyone would deny that. Certainly not I. Let's call "I want late-bound defaults and Python doesn't have them" Problem A. Let's call "I want my default value not to be evaluated until needed" Problem B. (Of course, you may not consider either to be a problem, but let's assume that you think that at least one of them is.) Chris is offering a PEP and an implementation which addresses Problem A. If Problem B is a problem for you, you can (currently) use a sentinel value, and explicitly evaluate the default when you want it. Not so terrible. In fact arguably, more often than not, better, because it's explicit. And more flexible (you can evaluate a different expression, or in a different scope, in different places in the function body). Chris/PEP 671 is not attempting to provide a better way of doing that. He is not offering Deferred Evaluation Objects (DEOs). Maybe in 5 years or so someone will offer an implementation of that, and everyone can be happy. Meanwhile, *Chris is offering a solution of Problem A*. He is *NOT addressing Problem B* - someone else is welcome to try that. Let's be honest: PEP 671 does not allow you to do anything you can't already. What is adds is some more convenience, some more concision, and arguably (and I *would* argue, in appropriate cases) some more readability. Why do people keep obscuring the discussion of a PEP which addresses Problem A by throwing in discussion of the (unrelated) Problem B? (Chris, and I, have stated, ad nauseam, that these *are* unrelated problems. If you don't agree, I can only ask you to consider the implementations necessary to solve each. If that doesn't change your mind, I have to throw my hands in the air and say "We'll have to agree to differ".) *Surely solving one "problem" is better than dithering about which "problem" to solve.* I've been accused of trying to censor this thread, but really - I'm just frustrated when people are invited to comment on PEP 671, and they don't comment on PEP 671, but on something else. BTW Thank you Stephen Turnbull, for your measured comments to this thread. 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/GOI65D2YBUYIYOXX2QK3MTRLI2VOBG3R/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 21 Jun 2022 at 10:13, Rob Cliffe via Python-ideas wrote: > > On 19/06/2022 04:42, David Mertz, Ph.D. wrote: > > On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe >> >> Sorry again, but IMO discussing any model except one where late-bound >> defaults are evaluated at function call time is just adding FUD. > > > It's definitely rude to repeatedly state that anyone who's opinion is > different from yours is "adding FUD" and doesn't belong in the thread. > > I was not talking about people whose opinion was different from mine. I was > talking about people who obscured the discussion of a proposal by talking > about a different proposal. And that, IMO, would be rude if it were done > deliberately, though I accept that it wasn't. > > > The topic of "late binding in function signatures" simply isn't *orthogonal* > to "late binding in the general sense." Yes, they are distinct, but very > closely adjacent. > > We disagree about that. Please consider the *IMPLEMENTATIONS* of each. I > respectfully suggest that you may conclude that they are not so close after > all. > > PS In my support may I quote from a post from Chris: > > [Steven D'Aprano] Chris may choose to reject this generalised lazy evaluation > idea, but if > so it needs to go into a Rejected Ideas section. Or he may decide that > actually having a generalised lazy evaluation idea is *brilliant* and > much nicer than making defaults a special case. > > [Chris] It's an almost completely orthogonal proposal. I used to have a > reference to it in the PEP but removed it because it was unhelpful. > Since it appears to matter to people, I've readded a mention of it. It's just freshly pushed so you might not see it instantly, but within a few minutes (or browse the source code on GitHub), you should see deferred evaluation mentioned in PEP 671. 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/OVN6E37EB73TZIW7EPKJWFDAGR47CQO2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 19/06/2022 04:42, David Mertz, Ph.D. wrote: On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe Sorry again, but IMO discussing any model except one where late-bound defaults are evaluated at function call time is just adding FUD. It's definitely rude to repeatedly state that anyone who's opinion is different from yours is "adding FUD" and doesn't belong in the thread. I was not talking about people whose opinion was different from mine. I was talking about people who obscured the discussion of a proposal by talking about a different proposal. And that, IMO, would be rude if it were done deliberately, though I accept that it wasn't. The topic of "late binding in function signatures" simply isn't *orthogonal* to "late binding in the general sense." Yes, they are distinct, but very closely adjacent. We disagree about that. *Please consider the */_**IMPLEMENTATIONS**_/*of each. I respectfully suggest that you may conclude that they are not so close after all. *PS In my support may I quote from a post from Chris: [Steven D'Aprano] Chris may choose to reject this generalised lazy evaluation idea, but if so it needs to go into a Rejected Ideas section. Or he may decide that actually having a generalised lazy evaluation idea is *brilliant* and much nicer than making defaults a special case. [Chris] It's an almost completely orthogonal proposal. I used to have a reference to it in the PEP but removed it because it was unhelpful. 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/LZVHCT42ISSJSOHTC6KAENAZJD33C4ZT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 19/06/2022 04:42, David Mertz, Ph.D. wrote: On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe Sorry again, but IMO discussing any model except one where late-bound defaults are evaluated at function call time is just adding FUD. It's definitely rude to repeatedly state that anyone who's opinion is different from yours is "adding FUD" and doesn't belong in the thread. I was not talking about people whose opinion was different from mine. I was talking about people who obscured the discussion of a proposal by talking about a different proposal. And that, IMO, would be rude if it were done deliberately, though I accept that it wasn't. Stephen, and Steven, and Paul, and I all perfectly well understand what "evaluated at function call time" means. I should jolly well hope so too. I certainly did not intend to suggest that any of you or anyone else do not understand it. And I can't see anything in any of my posts that suggests that I did intend that. Do you think that I did? If so, why? (Please quote where appropriate.) If I did somehow suggest that, I sincerely apologise. It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer characters, and moving an expression from the body to the signature. Yes, if you want to simplify a bit, basically it is. But it avoids the trap of the sentinel value being a possible parameter value. And it would answer a number of Stack Overflow posts on the lines of "Why doesn't this work [as I expected]?" I don't think that anyone, including Chris, would say that it allows you to do something that you can't do already (though I might be wrong, but I believe Python is already Turing-complete ). The virtue of the PEP is that it adds some convenience and some clarity and some concision. (Concision *is* a virtue, ceteribus paribus - which often they are not.) I'm still -1 because I don't think the purpose alone is close to worth the cost of new syntax... And especially not using sigils that are confusing to read in code. You complain about sigils. Do you accept my point that more **words** (and words that can, perhaps a trifle unkindly, be classed as boilerplate rather than genuine content) can also make stuff harder to read? The topic of "late binding in function signatures" simply isn't *orthogonal* to "late binding in the general sense." Yes, they are distinct, but very closely adjacent. We disagree about that. *Please consider the */_**IMPLEMENTATIONS**_/*of each. I respectfully suggest that you may conclude that they are not so close after all.* 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/G734UNUDJLGFV362LDE4WIUI7AL4DWEA/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 20 Jun 2022 at 21:19, Steven D'Aprano wrote: > > (4) The guarantee that a late-bound default WILL be executed at > > function call time, can be useful, even essential (it could be > > time-dependent or it could depend on the values - default or otherwise - > > of other parameters whose values might be changed in the function > > body). > > Okay. But a generalised lazy evaluation mechanism can be used to > implement PEP 671 style evaluation. > > Let me see if I can give a good analogy... generalised lazy evaluation > is like having a car that can drive anywhere there is a road, at any > time of the day or night. Late-bound defaults is like having a car that > can only drive to the local mall and back, and only on Thursdays. > > That's okay if you want to drive to the local mall on Thursdays, but if > you could only have one option, which would be more useful? > Nice analogy. It doesn't hold up. Consider this function: def f(stuff, max=>len(stuff)): stuff.append(1) print(max) f([1,2,3]) How would you use lazy evaluation to *guarantee* the behaviour here? The only way I can imagine doing it is basically the same as I'm doing: that late-bound argument defaults *have special syntax and meaning to the compiler*. If they were implemented with some sort of lazy evaluation object, they would need (a) access to the execution context, so you can't just use a function; (b) guaranteed evaluation on function entry, regardless of when - if ever - it gets referred to; and (c) the ability to put it in the function header. The only one of those that overlaps with lazy evaluation is (c). Please stop arguing this point. It is a false analogy and until you can demonstrate *with code* that there is value in doing it, it is a massive red herring. Even if Python does later on grow a generalized lazy evaluation feature, it will only change the *implementation* of late-bound argument defaults, not their specification. 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/2KA7SZAEWNH55HNEMK6H3UHWC5TZTS2Y/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, Jun 19, 2022 at 02:21:16AM +0100, Rob Cliffe via Python-ideas wrote: > Sorry, but I think all this talk about lazy evaluation is a big red herring: > (1) Python is not Haskell or Dask. Python is not Haskell, but we stole list comprehensions and pattern matching from it. Python steals concepts from many languages. And Python might not be Dask, but Dask is Python. https://www.dask.org/ > (2) Lazy evaluation is something Python doesn't have, Python has lazily evaluated sequences (potentially infinite sequences) via generators and iterators. We also have short-circuit evaluation, which is a form of lazy evaluation. There may be other examples as well. We may also get lazy importing soon: https://peps.python.org/pep-0690/ At last one of Python's direct competitors in the scientific community, R, has lazy evaluation built in. > and would be > a HUGE amount of work for Chris (or anyone) to implement I don't know how hard it is to implement lazy evaluation, but speaking with the confidence of the ignorant, I expect not that hard if you don't care too much about making it super efficient. A lazy expression, or thunk, is basically just a zero-argument function that the interpreter knows to call. If you don't care about getting Haskell levels of efficiency, that's probably pretty simple to implement. Rewriting Python from the ground up to be completely lazy like Haskell would be a huge amount of work. Adding some sort of optional and explicit laziness, like R and F# and other languages use, would possibly be little more work than just adding late-bound defaults. Maybe. > And in the unlikely event > that Chris (or someone) DID implement it, I expect there would be a > chorus of "No, no, that's not how (I think) it should work at all". The idea is that you plan your feature's semantics before writing an implementation. Even if you plan to "write one to throw away", and do exploratory coding, you should still have at least a vague idea of the desired semantics before you write a single line of code. > (3) Late-bound defaults that are evaluated at function call time, > as per PEP 671, give you an easy way of doing something that at present > needs one of a number of workarounds (such as using sentinel values) all > of which have their drawbacks or awkward points. Yes, we've read the PEP thank you :-) Late-bound defaults also have their own drawbacks. It is not a question of whether this PEP has any advantages. It clearly does! The question is where the balance of pros versus cons falls. > (4) The guarantee that a late-bound default WILL be executed at > function call time, can be useful, even essential (it could be > time-dependent or it could depend on the values - default or otherwise - > of other parameters whose values might be changed in the function > body). Okay. But a generalised lazy evaluation mechanism can be used to implement PEP 671 style evaluation. Let me see if I can give a good analogy... generalised lazy evaluation is like having a car that can drive anywhere there is a road, at any time of the day or night. Late-bound defaults is like having a car that can only drive to the local mall and back, and only on Thursdays. That's okay if you want to drive to the local mall on Thursdays, but if you could only have one option, which would be more useful? > Sure, I appreciate that there are times when you might want to > defer the evaluation because it is expensive and might not be needed, but: > (5) If you really want deferred evaluation of a parameter default, > you can achieve that by explicitly evaluating it, *at the point you want > it*, in the function body. Explicit is better than implicit. That's not really how lazy evaluation works or why people want it. The point of lazy evaluation is that computations are transparently and automatically delayed until you actually need them. Lazy evaluation is kind of doing the same thing for CPUs as garbage collection does for memory. GC kinda sorta lets you pretend you have infinite memory (so long as you don't actually try to use it all at once...). Lazy evaluation kinda sorta lets you pretend your CPU is infinitely fast (so long as you don't try to actually do too much all at once). If you think about the differences between generators and lists, that might help. A generator isn't really like a list that you just evaluate a few lines later. Its a completely different way of thinking about code, and often (but not always) better. > IMO lazy evaluation IS a different, orthogonal proposal. Late-bound defaults is a very small subset of lazy evaluation. But yes, lazy evaluation is a different, bigger concept. -- 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
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
@Chris My bottom line, as I wrote before, is that even if this were introduced, I probably will continue to default to def foo(arg=None): if arg is None: arg = default in my own code until I start seeing "def foo(arg=>default)" in a lot of code I read. Since Mailman generally supports about 4 Python versions, that means I won't see it in Mailman until 2027 or so. But I'm not George Bush to say "Read my lips: no new (syn)taxes!" Unless somebody comes up with some new really interesting use case, I think the suggestion somebody (sorry to somebody!) made earlier to "Just Do It" and submit to the SC is the right one. Both David and I are convinced that there is value-added in late binding for new mutables and defaults that are computed from actual arguments, even if we're not convinced it's enough. The proposal has plenty of fans, who *are* convinced and *will* use it. I don't see a prospect for that new really interesting use case, at least not here on Python-Ideas, the discussion is just variations on the same themes. On the other hand, a PEP under consideration may get a little more interest from the Python-Dev crowd, and obviously the SC itself. They may have use cases or other improvements to offer. "Now is better than never." The SC will let you know if the companion koan is applicable. ;-) @Chris You may or may not want to read my variations on the themes. ;-) Chris Angelico writes: > > In the numeric stuff, if I have: > > > > newarray = (A @ B) | (C / D) + (E - F) > > > > > > That's @, |, /, +, and -. So 5 operators, and 25 "complexity > > points". If I added one more operator, 36 "complexity points" > > seems reasonable. And if I removed one of those operators, 16 > > "complexity points" feels about right. > > For my part, I would say that it's quite the opposite. This is three > parenthesized tokens, each of which contains two things combined in a > particular way. That's six 'things' combined in particular ways. > Cognitive load is very close to this version: > > newarray = (A * B) + (C * D) + (E * F) I don't have the studies offhand, but "7 plus or minus 2" is famous enough, google that and you'll find plenty. I'll bet you even find "cognitive complexity of mathematical formulae" in the education literature. (And if not, we should sue all the Departments of Education in the world for fraud. ;-) I do have the words: "this is a sum of binary products". This basically reduces the cognitive complexity to two concepts plus a scan of the list of variables. Given that they're actually in alphabetical order, "first variable is A" is enough to reproduce the expression. That's much simpler than trying to describe David's 5-operator case with any degree of specificity. Or even just try to reproduce his formula without a lot of effort to memorize it! Also, just from the regularity of the form and its expression as an algebraic formula, I can deduce that almost certainly A, C, and E have the same type, and B, D, and F have the same type, and very likely those two types are the same. Not so for the five-operator case, where I would be surprised if less than 3 types were involved. Of course, this type information is probably redundant. I probably remember not only the types, but lots of other attributes of A through F. But this kind of redundancy is good! It reinforces my understanding of the expression and the program that surrounds it. > even though this uses a mere two operators. It's slightly more, but > not multiplicatively so. (The exact number of "complexity points" will > depend on what A through F represent, but the difference between "all > multiplying and adding" and "five distinct operators" is only about > three points.) That may be true for you, but it's definitely not true for my economics graduate students. > > Sure, knowing what `hi` defaults to *could be useful*. I'm sure > > if I used that function I would often want to know... and also > > often just assume the default is "something sensible." I just > > don't think that "could be useful" as a benefit is nearly as > > valuable as the cost of a new sigil and a new semantics adding to > > the cognitive load of Python. > > Yes, but "something sensible" could be "len(stuff)", "len(stuff)-1", > or various other things. Knowing exactly which of those will tell you > exactly how to use the function. @David: I find the "hi=len(stuff)" along with the "lst=[]" examples fairly persuasive (maybe moves me to +/- 0). @Chris: It would be a lot more persuasive if you had a plausible explicit list of "various other things". Even "len(stuff) - 1" is kind of implausible, given Python's consistent 0-based indexing and closed-open ranges (yeah, I know some people like to use the largest value in the range rather than the least upper bound not in the range, but I consider that bad style in Python, and they denote the same semantics).
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 20 Jun 2022 at 05:02, David Mertz, Ph.D. wrote: > > On Sun, Jun 19, 2022 at 2:24 PM Chris Angelico wrote: >> >> > def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG): >> > ... >> >> Is there any value in not putting that into a global constant? > > > Probably not. I was just inventing an ad hoc example to show what I meant. > I didn't search any actual repos I work on for real-life examples. Ah okay. Well, if that WERE a real example, I would recommend giving it a name. (Also, it's probably going to end up using >= rather than ==, so that the verbosity of any function can be set to a minimum level, so there'd be more complexity, thus making it even more useful to make it some sort of constant.) >> >> Regardless, the @ operator is now available *everywhere* in Python. Does it >> quadratically increase cognitive load? > > > Yeah, probably about that much. Other than NumPy or closely related array > libraries, I don't know that many other uses. I think I saw something on PyPI > that used it as an email thing, where obviously it has some familiarity. But > in that case, the lines it occurs on probably have no more than one or two > other sigils. > > In the numeric stuff, if I have: > > newarray = (A @ B) | (C / D) + (E - F) > > > That's @, |, /, +, and -. So 5 operators, and 25 "complexity points". If I > added one more operator, 36 "complexity points" seems reasonable. And if I > removed one of those operators, 16 "complexity points" feels about right. For my part, I would say that it's quite the opposite. This is three parenthesized tokens, each of which contains two things combined in a particular way. That's six 'things' combined in particular ways. Cognitive load is very close to this version: newarray = (A * B) + (C * D) + (E * F) even though this uses a mere two operators. It's slightly more, but not multiplicatively so. (The exact number of "complexity points" will depend on what A through F represent, but the difference between "all multiplying and adding" and "five distinct operators" is only about three points.) So unless you have a study showing this, I would say we each have a single data point - ourselves - and it's basically useless data. >> In a function signature "def bisect(stuff, lo=0, hi=None)", you don't >> know what the hi value actually defaults to. Even if it's obvious that >> it is late-bound > > > Sure, knowing what `hi` defaults to *could be useful*. I'm sure if I used > that function I would often want to know... and also often just assume the > default is "something sensible." I just don't think that "could be useful" > as a benefit is nearly as valuable as the cost of a new sigil and a new > semantics adding to the cognitive load of Python. > Yes, but "something sensible" could be "len(stuff)", "len(stuff)-1", or various other things. Knowing exactly which of those will tell you exactly how to use the function. Would you say that knowing that lo defaults to 0 is useful information? You could just have a function signature that merely says which arguments are mandatory and which are optional, and force people to use the documentation to determine the behaviour of omitted arguments. If you accept that showing "lo=0" gives useful information beyond simply that lo is optional, then is it so hard to accept that "hi=>len(stuff)" is also immensely valuable? > For example, it also "could be useful" to have syntax that indicated the > (expected) big-O complexity of that function. But whatever that syntax was, > I really doubt it would be worth the extra complexity in the language vs. > just putting that info in the docstring. > That's true; there's always a lot more that could go into a function's docstring than can fit into its signature. Perhaps, if it's of value to your project, it would be useful to use a function decorator and then redefine the return value annotation to (also or instead) inform you of the complexity. But for information about a single argument, the only useful place to put it is on the argument itself - either in the signature, or in a duplicated block in the docstring. And function defaults are a lot broader in value than algorithmic complexity, which is irrelevant to a huge number of functions. > Let's look at a function that has a lot of late-bound default arguments: > > pd.read_csv( > filepath_or_buffer: 'FilePath | ReadCsvBuffer[bytes] | > ReadCsvBuffer[str]', > sep=, > delimiter=None, > header='infer', > names=, > index_col=None, > usecols=None, > squeeze=None, > prefix=, > mangle_dupe_cols=True, > dtype: 'DtypeArg | None' = None, > engine: 'CSVEngine | None' = None, > converters=None, > true_values=None, > false_values=None, > skipinitialspace=False, > skiprows=None, > skipfooter=0, > nrows=None, > na_values=None, > keep_default_na=True, > na_filter=True, > verbose=False, >
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, Jun 19, 2022 at 2:24 PM Chris Angelico wrote: > > def frobnicate(data, > verbose=os.environ.get('LEVEL')==loglevel.DEBUG): ... > > Is there any value in not putting that into a global constant? > Probably not. I was just inventing an ad hoc example to show what I meant. I didn't search any actual repos I work on for real-life examples. > Regardless, the @ operator is now available *everywhere* in Python. Does > it quadratically increase cognitive load? > Yeah, probably about that much. Other than NumPy or closely related array libraries, I don't know that many other uses. I think I saw something on PyPI that used it as an email thing, where obviously it has some familiarity. But in that case, the lines it occurs on probably have no more than one or two other sigils. In the numeric stuff, if I have: newarray = (A @ B) | (C / D) + (E - F) That's @, |, /, +, and -. So 5 operators, and 25 "complexity points". If I added one more operator, 36 "complexity points" seems reasonable. And if I removed one of those operators, 16 "complexity points" feels about right. In a function signature "def bisect(stuff, lo=0, hi=None)", you don't > know what the hi value actually defaults to. Even if it's obvious that > it is late-bound Sure, knowing what `hi` defaults to *could be useful*. I'm sure if I used that function I would often want to know... and also often just assume the default is "something sensible." I just don't think that "could be useful" as a benefit is nearly as valuable as the cost of a new sigil and a new semantics adding to the cognitive load of Python. For example, it also "could be useful" to have syntax that indicated the (expected) big-O complexity of that function. But whatever that syntax was, I really doubt it would be worth the extra complexity in the language vs. just putting that info in the docstring. Let's look at a function that has a lot of late-bound default arguments: pd.read_csv( filepath_or_buffer: 'FilePath | ReadCsvBuffer[bytes] | ReadCsvBuffer[str]', sep=, delimiter=None, header='infer', names=, index_col=None, usecols=None, squeeze=None, prefix=, mangle_dupe_cols=True, dtype: 'DtypeArg | None' = None, engine: 'CSVEngine | None' = None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression: 'CompressionOptions' = 'infer', thousands=None, decimal: 'str' = '.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors: 'str | None' = 'strict', dialect=None, error_bad_lines=None, warn_bad_lines=None, on_bad_lines=None, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options: 'StorageOptions' = None, I'd have to look through the implementation, but my guess is that quite a few of the 25 late-bound defaults require calculations to set that take more than one line of code. I really don't WANT to know more than "this parameter is calculated according to some logic, perhaps complex logic" ... well, unless I think it pertains to something I genuinely want to configure, in which case I'll read the docs. -- 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/MPDHT2IF5O32AECZKQSYW7AKV6QWGV3X/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 20 Jun 2022 at 03:06, David Mertz, Ph.D. wrote: >> >> > I guess '>=' also looks "confusable", but it's far less common in >> > signatures, and the meaning is further away. >> >> It's no less valid than your other examples, nor less common (why >> would you have "==" in a function signature, for instance?). > > > I guess I probably use `==` more often in function calls and signatures, on > reflection. In call, I use `==` quite often to pass some boolean switch > value, and `>=` much less often. Obviously, I am aware that `>=` also > produces a boolean result, and YMMV on how often comparing for equality and > inequality expresses the flag you want. > > In signature, I'd really only use it, I reckon, as a "default default." E.g. > > def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG): ... > > This supposes I have an environmental setting for verbosity that I usually > want to use, but might override that on a particular call. Okay. When it comes to finding causes for the difficulty of reading your function signatures, I think this is a far greater one *in a vacuum* than having support for late-bound defaults. Maybe it's not a problem *for you* because you're accustomed to reading that as a single token, but that can be true of any sequence. Is there any value in not putting that into a global constant? >> >> > I think the cognitive complexity of a line with sigils is somewhere around >> > quadratic or cubic on the number of distinct sigils. But when several look >> > similar, it quickly tends toward the higher end. And when several have >> > related meanings, it's harder still to read. >> >> It shouldn't need to be. Once you know how expressions are built up, it >> should give linear complexity. > > > I'm not talking about the big-O running time of some particular engine that > parses a BNF grammar here. I'm talking about actual human brains, which work > differently. Yes, and human brains are fine with adding more options, as long as they work the same way that other options do. > I don't have data for my quadratic and cubic guesses. Just 40 years of my > own programming experience, and about the same amount of time watching other > programmers. > > It would be relatively easy to measure if one wanted to. But it's a > cognitive psychology experiment. You need to get a bunch of people in rooms, > and show them lots of code lines. Then measure error rates and response > times in their answers. That sort of thing. The protocol for this > experiment would need to be specified more carefully, of course. But it *is* > the kind of thing that can be measured in human beings. > > So my (very strong) belief is that a human being parsing a line with 5 sigils > in it will require MUCH MORE than 25% more effort than parsing a line with 4 > sigils in it. As in, going from 4 to 5 distinct sigils in the same line > roughly DOUBLES cognitive load. Here the distinctness is important; it's not > at all hard to read: > > a + b + c + d + e + f + g + h + i Okay. You run a test, and let's see how it goes. At the moment, all you have is a single data point: yourself. Specifically, yourself with all your current knowledge. I think it's a little biased. :) >> Did the introduction of the @ (matrix multiplication) operator to >> Python increase the language's complexity multiplicatively, or >> additively? Be honest now: are your programs more confusing to read >> because @ could have been *, because @ could have been +, because @ >> could have been ==, etc etc etc, or is it only that @ is one new >> operator, additively with the other operators? > > > I'm not sure how much you know about the background of this in the NumPy > world. While other libraries have also now used that operator, NumPy was the > driving force. > > In the old days, if I wanted to do a matrix multiply, I would either do: > > A_matrix = np.matrix(A) > B_matrix = np.matrix(B) > > result = A_matrix * B_matrix > > Or alternately: > > result = np.dot(A, B) > > > Neither of those approaches are terrible, but in more complex expressions > where the dot product is only part of the expression, indeed `A @ B` reads > better. Regardless, the @ operator is now available *everywhere* in Python. Does it quadratically increase cognitive load? >> > When I write an expression like 'a - b * c / d**e + f' that also has a >> > bunch of symbols. But they are symbols that: >> > >> > - look strongly distinct >> > - have meanings familiar from childhood >> > - have strongly different meanings (albeit all related to arithmetic) >> >> The double asterisk wasn't one that I used in my childhood, yet in >> programming, I simply learned it and started using it. What happens is >> that known concepts are made use of to teach others. > > > I didn't learn the double asterisk in school either. That I had to learn in > programming languages. I actually prefer those programming languages that > use `^` for
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
> > > I guess '>=' also looks "confusable", but it's far less common in > signatures, and the meaning is further away. > > It's no less valid than your other examples, nor less common (why > would you have "==" in a function signature, for instance?). > I guess I probably use `==` more often in function calls and signatures, on reflection. In call, I use `==` quite often to pass some boolean switch value, and `>=` much less often. Obviously, I am aware that `>=` also produces a boolean result, and YMMV on how often comparing for equality and inequality expresses the flag you want. In signature, I'd really only use it, I reckon, as a "default default." E.g. def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG): ... This supposes I have an environmental setting for verbosity that I usually want to use, but might override that on a particular call. > > I think the cognitive complexity of a line with sigils is somewhere > around quadratic or cubic on the number of distinct sigils. But when > several look similar, it quickly tends toward the higher end. And when > several have related meanings, it's harder still to read. > > It shouldn't need to be. Once you know how expressions are built up, it > should give linear complexity. > I'm not talking about the big-O running time of some particular engine that parses a BNF grammar here. I'm talking about actual human brains, which work differently. I don't have data for my quadratic and cubic guesses. Just 40 years of my own programming experience, and about the same amount of time watching other programmers. It would be relatively easy to measure if one wanted to. But it's a cognitive psychology experiment. You need to get a bunch of people in rooms, and show them lots of code lines. Then measure error rates and response times in their answers. That sort of thing. The protocol for this experiment would need to be specified more carefully, of course. But it *is* the kind of thing that can be measured in human beings. So my (very strong) belief is that a human being parsing a line with 5 sigils in it will require MUCH MORE than 25% more effort than parsing a line with 4 sigils in it. As in, going from 4 to 5 distinct sigils in the same line roughly DOUBLES cognitive load. Here the distinctness is important; it's not at all hard to read: a + b + c + d + e + f + g + h + i And in the weeds, the particular sigils involved (and even the font they're rendered in) will make a difference too. As well it matters the "semantic proximity" of the various operators. And other factors too I'm sure. Did the introduction of the @ (matrix multiplication) operator to > Python increase the language's complexity multiplicatively, or > additively? Be honest now: are your programs more confusing to read > because @ could have been *, because @ could have been +, because @ > could have been ==, etc etc etc, or is it only that @ is one new > operator, additively with the other operators? > I'm not sure how much you know about the background of this in the NumPy world. While other libraries have also now used that operator, NumPy was the driving force. In the old days, if I wanted to do a matrix multiply, I would either do: A_matrix = np.matrix(A) B_matrix = np.matrix(B) result = A_matrix * B_matrix Or alternately: result = np.dot(A, B) Neither of those approaches are terrible, but in more complex expressions where the dot product is only part of the expression, indeed `A @ B` reads better. And yes, expressions on NumPy arrays will often use a number of those arithmetic operators I learned in grade school as well as `@`. But generally, the mathematics expressed in NumPy code is irreducible complexity. It's not necessarily easy to parse visually, but it *IS* the underlying mathematics. > > When I write an expression like 'a - b * c / d**e + f' that also has a > bunch of symbols. But they are symbols that: > > > > - look strongly distinct > > - have meanings familiar from childhood > > - have strongly different meanings (albeit all related to arithmetic) > > The double asterisk wasn't one that I used in my childhood, yet in > programming, I simply learned it and started using it. What happens is > that known concepts are made use of to teach others. I didn't learn the double asterisk in school either. That I had to learn in programming languages. I actually prefer those programming languages that use `^` for exponentiation (in that one aspect, not overall more than Python), because it's more reminiscent of superscript. Is that simply because you already are familiar with those operators, > or is there something inherently different about them? Would it really > be any different? > It's a mixture of familiarity and actual visual distinctness. `/` and `+` really do just *look different*. In contrast `:=` and `=` just really look similar. Then don't use it in a signature. That's fine. Personally, I've never > used the "def
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, Jun 19, 2022, 12:02 PM Chris Angelico > I've no idea what you mean by "sophistical" here. Please explain? > 1. of or characteristic of sophists or sophistry 2. clever and plausible, but unsound and tending to mislead a sophistical argument 3. using sophistry Plato's dialog _The Sophist_ is good background. ___ 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/GH3TETOF4YHWGJ66FTJFNPLFKCUDCQR2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 20 Jun 2022 at 01:37, David Mertz, Ph.D. wrote: > > Unfortunately, in relation to this PEP, I find your arguments tend to be > sophistical. They ate not generally so in other threads, but for whatever > reason your attachment to this has a different quality. > I've no idea what you mean by "sophistical" here. Please explain? > There's an interesting point you raise though. You seem to feel that closely > related meanings should have similar looking sigils. I'm not sure my opinion > is *opposite *, but it's definitely more that subtly different semantics > should not be marked by easily visually confusable sigils. > > Under PEP 671, a single line of a function signature might contain '=', ':=', > '=>', '->', ':', and '=='. Obviously it can have other symbols as well. But > those are the ones the most blur into each other visually. 4 of them have > closely related meanings. You don't even need to be contrived to have such > examples. > Yes, but only some of those are actually part of the signature itself. I mean, if you put a lambda function into the default value, you could have even more colons: def f(x:int=lambda x: x+1, y:object=(_default:=object())): ... But that's just what happens when syntax is nestable. We almost never restrict code to using an arbitrary subset of Python syntax just because otherwise there'd be similar symbols in the same vicinity. Even when it's a problem for the parser, the solution is often just parentheses. > I guess '>=' also looks "confusable", but it's far less common in signatures, > and the meaning is further away. > It's no less valid than your other examples, nor less common (why would you have "==" in a function signature, for instance?). > Below you seem to try another unconvincing reductio ad absurdum to suggest > that I must either want a language with no symbols or support this PEP. > > I think the cognitive complexity of a line with sigils is somewhere around > quadratic or cubic on the number of distinct sigils. But when several look > similar, it quickly tends toward the higher end. And when several have > related meanings, it's harder still to read. > It shouldn't need to be. Once you know how expressions are built up, it should give linear complexity. Did the introduction of the @ (matrix multiplication) operator to Python increase the language's complexity multiplicatively, or additively? Be honest now: are your programs more confusing to read because @ could have been *, because @ could have been +, because @ could have been ==, etc etc etc, or is it only that @ is one new operator, additively with the other operators? Even when syntactically it's multiplicative, it's often possible to be merely additive in cognitive burden. Augmented assignment broadly functions as a single feature - "x #= y" parallels "x = x # y" for any operator where that's legal. > When I write an expression like 'a - b * c / d**e + f' that also has a bunch > of symbols. But they are symbols that: > > - look strongly distinct > - have meanings familiar from childhood > - have strongly different meanings (albeit all related to arithmetic) > The double asterisk wasn't one that I used in my childhood, yet in programming, I simply learned it and started using it. What happens is that known concepts are made use of to teach others. It's the same with every feature, and this one is no different: if you already understand "def f(x=1)", it is only a small step to "def f(x=>[])", and everything you already know is still valid. > Yes, I probably have to think for a while about operator precedence to make > sure I understand it. Probably I'll add some redundant parens if I can edit > the code. But the cognitive burden of the sigils remains FAR lower than what > would occur with regularity under PEP 671. > Is that simply because you already are familiar with those operators, or is there something inherently different about them? Would it really be any different? > I already dislike the walrus operator in signature context for that reason... > although I think it's great for e.g. 'while a := getdata() > 0: ...' > Then don't use it in a signature. That's fine. Personally, I've never used the "def f(x=_sentinel:=object())" trick, because it has very little value - it makes the function header carry information that actually isn't part of the function signature (that the object is also in the surrounding context as "_sentinel" - the function's caller can't use that information), and doesn't have any real advantages over just putting it a line above. But that's because of what the feature does, not how it's spelled. An expression is an expression. Any competent programmer should be able to read them as such. 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
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Unfortunately, in relation to this PEP, I find your arguments tend to be sophistical. They ate not generally so in other threads, but for whatever reason your attachment to this has a different quality. There's an interesting point you raise though. You seem to feel that closely related meanings should have similar looking sigils. I'm not sure my opinion is *opposite *, but it's definitely more that subtly different semantics should not be marked by easily visually confusable sigils. Under PEP 671, a single line of a function signature might contain '=', ':=', '=>', '->', ':', and '=='. Obviously it can have other symbols as well. But those are the ones the most blur into each other visually. 4 of them have closely related meanings. You don't even need to be contrived to have such examples. I guess '>=' also looks "confusable", but it's far less common in signatures, and the meaning is further away. Below you seem to try another unconvincing reductio ad absurdum to suggest that I must either want a language with no symbols or support this PEP. I think the cognitive complexity of a line with sigils is somewhere around quadratic or cubic on the number of distinct sigils. But when several look similar, it quickly tends toward the higher end. And when several have related meanings, it's harder still to read. When I write an expression like 'a - b * c / d**e + f' that also has a bunch of symbols. But they are symbols that: - look strongly distinct - have meanings familiar from childhood - have strongly different meanings (albeit all related to arithmetic) Yes, I probably have to think for a while about operator precedence to make sure I understand it. Probably I'll add some redundant parens if I can edit the code. But the cognitive burden of the sigils remains FAR lower than what would occur with regularity under PEP 671. I already dislike the walrus operator in signature context for that reason... although I think it's great for e.g. 'while a := getdata() > 0: ...' On Sun, Jun 19, 2022, 10:31 AM Chris Angelico wrote: > On Mon, 20 Jun 2022 at 00:06, David Mertz, Ph.D. > wrote: > > > > On Sun, Jun 19, 2022, 3:27 AM Chris Angelico > >> > >> > I'm still -1 because I don't think the purpose alone is close to > worth the cost of new syntax... And especially not using sigils that are > confusing to read in code. > >> > > >> > The topic of "late binding in function signatures" simply isn't > *orthogonal* to "late binding in the general sense." Yes, they are > distinct, but very closely adjacent. > >> > >> Every argument you've just made is ALSO an argument against function > defaults in general. Do you think that they aren't worth syntax either? > > > > > > I honestly can find no connection between what I've argued and "function > defaults in general." It feels like a non sequitur, but I accept that they > somehow connect in your mind. > > > > Let's go through the arguments you laid out. > > > It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer > characters, and moving an expression from the body to the signature. > > > > That's what ALL argument defaults do. Some languages evaluate them > early, some evaluate them late. > > > I'm still -1 because I don't think the purpose alone is close to worth > the cost of new syntax... > > > > What purpose? Being able to define the function's signature in its > signature, including the meaning of omitted arguments? That's > definitely the purpose of ALL default arguments, not just late-bound. > > > And especially not using sigils that are confusing to read in code. > > The sigils used are very similar here: "a=b" and "a=>b". Are you > really trying to tell me that "=" is not confusing to read in code, > but "=>" is, or are all such sigils equally confusing? Function > signatures already have several symbols other than those used for > defaults, including *, /, and :, not to mention ( ) and -> which > aren't inside the argument list, but are still part of the function > signature. Programmers are accustomed to working with symbols (with > the possible exception of COBOL and DeScribe Macro Language > programmers), and your argument would work just as well against any > sort of argument defaults. > > > The topic of "late binding in function signatures" simply isn't > *orthogonal* to "late binding in the general sense." Yes, they are > distinct, but very closely adjacent. > > This one, you specifically mention late binding, so that's the one > exception. > > Other than that, every one of your arguments could be used to show > that we shouldn't have ANY function argument defaults. Not one of them > justifies having default values without default expressions. > > > Way back last Oct when this discussion had it's first round, someone > (probably Steven, but maybe it was someone else) did a survey of a numerous > programming languages, and whether they use early binding or late binding > of default function arguments. > > > > The result was that
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, 20 Jun 2022 at 00:06, David Mertz, Ph.D. wrote: > > On Sun, Jun 19, 2022, 3:27 AM Chris Angelico >> >> > I'm still -1 because I don't think the purpose alone is close to worth the >> > cost of new syntax... And especially not using sigils that are confusing >> > to read in code. >> > >> > The topic of "late binding in function signatures" simply isn't >> > *orthogonal* to "late binding in the general sense." Yes, they are >> > distinct, but very closely adjacent. >> >> Every argument you've just made is ALSO an argument against function >> defaults in general. Do you think that they aren't worth syntax either? > > > I honestly can find no connection between what I've argued and "function > defaults in general." It feels like a non sequitur, but I accept that they > somehow connect in your mind. > Let's go through the arguments you laid out. > It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer > characters, and moving an expression from the body to the signature. > That's what ALL argument defaults do. Some languages evaluate them early, some evaluate them late. > I'm still -1 because I don't think the purpose alone is close to worth the > cost of new syntax... > What purpose? Being able to define the function's signature in its signature, including the meaning of omitted arguments? That's definitely the purpose of ALL default arguments, not just late-bound. > And especially not using sigils that are confusing to read in code. The sigils used are very similar here: "a=b" and "a=>b". Are you really trying to tell me that "=" is not confusing to read in code, but "=>" is, or are all such sigils equally confusing? Function signatures already have several symbols other than those used for defaults, including *, /, and :, not to mention ( ) and -> which aren't inside the argument list, but are still part of the function signature. Programmers are accustomed to working with symbols (with the possible exception of COBOL and DeScribe Macro Language programmers), and your argument would work just as well against any sort of argument defaults. > The topic of "late binding in function signatures" simply isn't *orthogonal* > to "late binding in the general sense." Yes, they are distinct, but very > closely adjacent. This one, you specifically mention late binding, so that's the one exception. Other than that, every one of your arguments could be used to show that we shouldn't have ANY function argument defaults. Not one of them justifies having default values without default expressions. > Way back last Oct when this discussion had it's first round, someone > (probably Steven, but maybe it was someone else) did a survey of a numerous > programming languages, and whether they use early binding or late binding of > default function arguments. > > The result was that MOST languages do late (call time) binding, albeit many > of those are compiled languages where early binding doesn't really make > sense. Some, like JavaScript don't have defaults at all, so the approach is > actually similar to Python: > > const myfunc = (a, b, c) => { > if (typeof c === 'undefined') { c = ... } > } Actually JavaScript does have argument defaults. (Also, I would write this as simply "if (c === undefined)", since there's no situation in which that would fail here.) The obvious syntax is equivalent to what you wrote: const myfunc = (a, b, c=...) => ... > That's a sentinel, but worse than Python in several ways. Not sure what you mean by "several", but it is indeed a simple sentinel, which has the downside that you can pass the special value undefined to the function. So I would say it's exactly equivalent to Python and the use of None, except that it's late-bound. > Others like Perl don't really have named arguments at all, but that weird > implicit list you can pop from. > JavaScript, being JavaScript, has that too - which is actually good, because it lets you distinguish between omitted arguments and those passed as undefined. I want to do *better* than those languages, not to use them as a pass mark. > The one thing that there were ZERO examples of elsewhere was what you > propose: slightly different syntax to allow both early-bound and late-bound. > Admittedly, if Python had done late-bound from 1.0, probably no one would now > have a PEP to add an early-bound spelling variant. > And yet early-bound argument defaults ARE of value. Maybe they wouldn't have been worth adding syntax for, but I would be highly confident that someone would have made a decorator for it: @freeze_defaults(x=1) def foo(x): ... And, since it's hard for a decorator to remap arguments perfectly, it would have done an imperfect job, but it might have been good enough to not ask for the feature. > If Python had always been late-bound, I'm sure I'd be perfectly happy with it > today. But sentinels are really easy, and obscure sigils are really hard. So > adding the new spelling just
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, Jun 19, 2022, 3:27 AM Chris Angelico > > I'm still -1 because I don't think the purpose alone is close to worth > the cost of new syntax... And especially not using sigils that are > confusing to read in code. > > > > The topic of "late binding in function signatures" simply isn't > *orthogonal* to "late binding in the general sense." Yes, they are > distinct, but very closely adjacent. > > Every argument you've just made is ALSO an argument against function > defaults in general. Do you think that they aren't worth syntax either? > I honestly can find no connection between what I've argued and "function defaults in general." It feels like a non sequitur, but I accept that they somehow connect in your mind. Way back last Oct when this discussion had it's first round, someone (probably Steven, but maybe it was someone else) did a survey of a numerous programming languages, and whether they use early binding or late binding of default function arguments. The result was that MOST languages do late (call time) binding, albeit many of those are compiled languages where early binding doesn't really make sense. Some, like JavaScript don't have defaults at all, so the approach is actually similar to Python: const myfunc = (a, b, c) => { if (typeof c === 'undefined') { c = ... } } That's a sentinel, but worse than Python in several ways. Others like Perl don't really have named arguments at all, but that weird implicit list you can pop from. The one thing that there were ZERO examples of elsewhere was what you propose: slightly different syntax to allow both early-bound and late-bound. Admittedly, if Python had done late-bound from 1.0, probably no one would now have a PEP to add an early-bound spelling variant. If Python had always been late-bound, I'm sure I'd be perfectly happy with it today. But sentinels are really easy, and obscure sigils are really hard. So adding the new spelling just makes Python worse. Beginners have something needless to learn, and experienced developers have just a little more cognitive burden all the time. > ___ 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/4TMLNYHBLQEY3TBWLH3S3DEDCFWN2Q2M/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, 19 Jun 2022 at 13:44, David Mertz, Ph.D. wrote: > > On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe >> >> Sorry again, but IMO discussing any model except one where late-bound >> defaults are evaluated at function call time is just adding FUD. > > > It's definitely rude to repeatedly state that anyone who's opinion is > different from yours is "adding FUD" and doesn't belong in the thread. > > Stephen, and Steven, and Paul, and I all perfectly well understand what > "evaluated at function call time" means. > > It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer > characters, and moving an expression from the body to the signature. > > I won't stoop to saying that advocating what you do is FUD. I can even > understand why someone would want that in Python. > > I'm still -1 because I don't think the purpose alone is close to worth the > cost of new syntax... And especially not using sigils that are confusing to > read in code. > > The topic of "late binding in function signatures" simply isn't *orthogonal* > to "late binding in the general sense." Yes, they are distinct, but very > closely adjacent. Every argument you've just made is ALSO an argument against function defaults in general. Do you think that they aren't worth syntax either? 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/EVLMB6GUZUK2LB4UXRITUSWDKYDTM3D7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe > Sorry again, but IMO discussing any model except one where late-bound > defaults are evaluated at function call time is just adding FUD. > It's definitely rude to repeatedly state that anyone who's opinion is different from yours is "adding FUD" and doesn't belong in the thread. Stephen, and Steven, and Paul, and I all perfectly well understand what "evaluated at function call time" means. It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer characters, and moving an expression from the body to the signature. I won't stoop to saying that advocating what you do is FUD. I can even understand why someone would want that in Python. I'm still -1 because I don't think the purpose alone is close to worth the cost of new syntax... And especially not using sigils that are confusing to read in code. The topic of "late binding in function signatures" simply isn't *orthogonal* to "late binding in the general sense." Yes, they are distinct, but very closely adjacent. ___ 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/INJ6O2MIJUU7ZML2P6SF47FRD7HOMMP6/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Sorry, but I think all this talk about lazy evaluation is a big red herring: (1) Python is not Haskell or Dask. (2) Lazy evaluation is something Python doesn't have, and would be a HUGE amount of work for Chris (or anyone) to implement (much more, I would think, than he has already put into his reference implementation of PEP 671). It's effectively asking for an implementation of that deferred evaluation vapourware that people keep talking about. It's not going to happen in a foreseeable time frame. And in the unlikely event that Chris (or someone) DID implement it, I expect there would be a chorus of "No, no, that's not how (I think) it should work at all". (3) Late-bound defaults that are evaluated at function call time, as per PEP 671, give you an easy way of doing something that at present needs one of a number of workarounds (such as using sentinel values) all of which have their drawbacks or awkward points. (4) The guarantee that a late-bound default WILL be executed at function call time, can be useful, even essential (it could be time-dependent or it could depend on the values - default or otherwise - of other parameters whose values might be changed in the function body). Sure, I appreciate that there are times when you might want to defer the evaluation because it is expensive and might not be needed, but: (5) If you really want deferred evaluation of a parameter default, you can achieve that by explicitly evaluating it, *at the point you want it*, in the function body. Explicit is better than implicit. Sorry again, but IMO discussing any model except one where late-bound defaults are evaluated at function call time is just adding FUD. I suppose I'll be accused again of trying to censor this thread for saying that. Well, as Chris said (as far as I recall ATM) there is a difference between discussing variants of a proposal and discussing orthogonal proposals (which could be raised in a separate thread). And IMO lazy evaluation IS a different, orthogonal proposal. There's nothing in the PEP about it. Best wishes Rob Cliffe On 18/06/2022 16:42, David Mertz, Ph.D. wrote: I think the example that Steven gave, and Stephen approximately repeats is good. def func(items=[], n=later len(items)): items.append("Hello") print(n) func() > I guess Chris will say 0 and David will say 1, but I might be wrong about either of them. This is correct. And even though using a (soft) keyword like this gets me to -0, the semantics I want indeed are different. I only want the binding to be evaluated when it is referenced. If it never gets referenced, the compassion time asked side effects are skipped. Of course, the first line of the function body could be `n = n`. But adding that line isn't so much different from starting with `if n is None: n = ... ` As to Stephen's comments on not having used the "evaluate on reference" pattern, that's pretty much not having used dask.deferred. The difference is that with Dask (or Haskell) everything stays lazy until you explicitly call `.compute()` on something in the DAG of operations. I'd prefer not to need that. But then my not-a-proposal would need a way to have "a reference that isn't a reference". I think the same keywords works. def func(items=[], n=later len(items)): items.append("Hello") n = later n**3 # n remains lazy # ... more stuff print(n) # actually evaluate the cube of length On Sat, Jun 18, 2022, 10:52 AM Stephen J. Turnbull wrote: Chris wants syntax for the common pattern def foo(arg_with_new_empty_list_default=None): if arg_with_new_empty_list_default is None: arg_with_new_empty_list_default = [] # do stuff I can't really guess how useful the "use point" version would be. It's not a pattern I've used, I use a zero-argument function very occasionally but I can't recall a case where I used a lambda ___ 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/RLFYYFG7T53F7XGFGWMTV3NWHWVP3LCU/ 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/RIVWFMBG47ILJNEVNMACCTE7YS7RWGGL/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 18/06/2022 03:28, Steven D'Aprano wrote: On Fri, Jun 17, 2022 at 06:32:36AM +0100, Rob Cliffe wrote: The bar for adding a new hard keyword to Python is very high. Likewise for new syntax. I would suggest less so, provided that it was previously illegal, because it's backward-compatible, unlike a new keyword. The suggestion is to add a new keyword to a PEP which absolutely doesn't need it, *shrug* Well, I have heard many times how high the bar is, so I'm surprised that suggesting a completely unnecessary one gets no more from you than a shrug. The match...case statement didn't "need" keywords either, we could have picked symbols instead if we wanted to look like APL. Remember that keywords have advantages as well as disadvantages. Given the existence of community support for keywords, the PEP should make the case that symbols are better in this case. Even if that's only "a majority prefer symbols". I did mention the readability issue towards the end of my post. on the grounds that it **might** (**not** would - we can't know without a spec) give compatibility with some fictional vapourware which - for all people keep talking about it - hasn't happened in years, isn't happening (AFAIK nobody is working on it), doesn't have anything remotely close to even an outline specification (people disagree as to what it should do), very likely never will happen, and at best won't happen for years. I think that is broadly accurate. Harsh but fair: nobody has a concrete plan for generalising "defer" keyword would do. It is still vapourware. Thank you. [...] def f(x = later -y): Is that a late-bound default of -y? Bad luck; it's already legal syntax for an early-bound default of `later` minus `y`. Good catch. Thank you. Late-bound defaults are meant to be evaluated at function call time (and in particular, not some way down in the function body when the parameter gets used). Not necessarily. I don't recall if this has been raised in this thread before, but it is possible to delay the evaluation of the default value until it is actually needed. I believe that this is how Haskell operates pretty much everywhere. (Haskell experts: do I have that correct?) Sorry, but what on earth is the relevance of this? Python is not Haskell. And it can be vital that the evaluation of late-default values is *not* delayed (it should be guaranteed if PEP 671 is accepted). Example 1: def f(startTime => timeNow()): < 10-minute calculation > endTime = timeNow() print('Elapsed time:', endTime-startTime) # Help, why is this printing "Elapsed time: -0.001"? Example 2: def g(x, y=>x**2): x = x+1 print(y) 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/RLQVS3Z26A7NTFNTC2EZA7C2FE42ZURH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I think the example that Steven gave, and Stephen approximately repeats is good. def func(items=[], n=later len(items)): items.append("Hello") print(n) func() > I guess Chris will say 0 and David will say 1, but I might be wrong about either of them. This is correct. And even though using a (soft) keyword like this gets me to -0, the semantics I want indeed are different. I only want the binding to be evaluated when it is referenced. If it never gets referenced, the compassion time asked side effects are skipped. Of course, the first line of the function body could be `n = n`. But adding that line isn't so much different from starting with `if n is None: n = ... ` As to Stephen's comments on not having used the "evaluate on reference" pattern, that's pretty much not having used dask.deferred. The difference is that with Dask (or Haskell) everything stays lazy until you explicitly call `.compute()` on something in the DAG of operations. I'd prefer not to need that. But then my not-a-proposal would need a way to have "a reference that isn't a reference". I think the same keywords works. def func(items=[], n=later len(items)): items.append("Hello") n = later n**3 # n remains lazy # ... more stuff print(n) # actually evaluate the cube of length On Sat, Jun 18, 2022, 10:52 AM Stephen J. Turnbull < stephenjturnb...@gmail.com> wrote: > Chris wants syntax for the common pattern > > def foo(arg_with_new_empty_list_default=None): > if arg_with_new_empty_list_default is None: > arg_with_new_empty_list_default = [] > # do stuff > > I can't really guess how useful the "use point" version would be. It's not > a pattern I've used, I use a zero-argument function very occasionally but I > can't recall a case where I used a lambda ___ 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/RLFYYFG7T53F7XGFGWMTV3NWHWVP3LCU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 15:53, Stephen J. Turnbull wrote: > I don't find that burdensome enough to want syntax, and I can't guess > how quickly I'd start using it if available, that probably depends on > how often the community seems to be using it (ie, in the code I'm > reading). To be honest, I think this is the real flaw with the proposal. It's somewhat attractive in theory, adding a short form for something which people do tend to write out "longhand" at the moment. But the saving is relatively small, and there are a number of vaguely annoying edge cases that probably don't come up often, but overall just push the proposal into the "annoyingly complicated" area. The net result is that we get something that *might* help with a minor annoyance, but the cost in (theoretical, but necessary) complexity is just a bit too high. Paul ___ 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/7WX3AAR7T3MR2NI7JFY3SJKWK4QIFGN5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Steven D'Aprano writes: > The match...case statement didn't "need" keywords either, we could have > picked symbols instead if we wanted to look like APL. Remember that > keywords have advantages as well as disadvantages. Given the existence > of community support for keywords, the PEP should make the case that > symbols are better in this case. The argument I would make is that in the presence of type annotations a keyword adds a lot of verbosity, and is possibly confusable (ie, ignorable) as a type component, and that that is sufficient argument for a symbol rather than a keyword. > This raises another choice: should lazy defaults be evaluated before > entering the body of the function, or at the point where the parameter > is used? Which would be more useful? Chris makes the point that we've been through this before so I won't belabor that point. Both are potentially useful. Chris wants syntax for the common pattern def foo(arg_with_new_empty_list_default=None): if arg_with_new_empty_list_default is None: arg_with_new_empty_list_default = [] # do stuff and variants (eg, where the default is a computation expensive enough that you don't want to do it if the argument is never defaulted). I don't find that burdensome enough to want syntax, and I can't guess how quickly I'd start using it if available, that probably depends on how often the community seems to be using it (ie, in the code I'm reading). I can't really guess how useful the "use point" version would be. It's not a pattern I've used, I use a zero-argument function very occasionally but I can't recall a case where I used a lambda (lambdas are kinda annoying). Adding the parens at the call is easy to forget, but not that huge a burden either. The only use case I can think of offhand is where the default is such an expensive computation that you don't want it done unless its result is actually used, and it might not be: def foo(flag, arg=None, *otherargs): if flag: if arg is None: arg = expensive_function return arg(*other_args) else: return a_constant On the one hand, it seems likely that a very expensive function is expensive enough to avoid at the cost of an obscure default and an if in the definition of foo. On the other the whole scenario seems rather contrived and not worth syntax. ___ 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/6Z7GD6STJQP7ABKINIMBNCVBS4BOSLOG/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Chris Angelico writes: > And there we have it. People are complaining loudly, but then ALSO > saying that they don't support the proposal anyway. Why are you > bothering to debate this if you've already made your decision? I can't speak for Brendan, but I have two reasons for discussing despite being broadly in sympathy with David Mertz's reasons for opposing the proposal: 1. Often enough I've disagreed with a proposal, only to see it implemented. Of course, I want the least bad version from my point of view. 2. More altruistically, even though I disagree with a proposal, I would be ashamed if I thought there was a way to improve a proposal, and didn't mention it in the hope of sabotaging the proposal's chances by leaving it less than it could be. That doesn't mean in either case I'm right, of course, but at least I can *try*. :-) Regards, 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/P7K2HAH3UM2OOONOOV45FSB3EUNDDA4C/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 03:45, Chris Angelico wrote: > > This raises another choice: should lazy defaults be evaluated before > > entering the body of the function, or at the point where the parameter > > is used? Which would be more useful? > > > > # `defer n=len(items)` > > def func(items=[], n=>len(items)): > > items.append("Hello") > > print(n) > > > > func() > > That's one of the problems. Generic lazy evaluation should be > processed at some point where the parameter is used, but late-bound > defaults are evaluated as the function begins. They are orthogonal. That sounds like an *extremely* good statement to make in the "Rejected suggestions" section of the PEP, explaining why the PEP's proposal and a "lazy evaluation" proposal are different. > At what point is an unrelated proposal a "rejected idea"? How > different does it have to be before it doesn't help to have it in that > section? At the point where people repeatedly offer it as an alternative to the PEP. If it's so unrelated as to make no sense at all, just add it as "XXX: rejected as it solves a different problem" or similar. But your response above is better for the lazy evaluation suggestion, and explains why you think it's unrelated. > You're welcome to keep on arguing for the sake of arguing, but you're > not actually accomplishing anything by it. Especially since you're > rehashing the exact same complaints that you raised previously, and > which I responded, exactly the same way, at the time. *Everyone* is just rehashing the same comments by this point. People are piling in because of a fear that if they don't, someone will claim that we now have consensus, not because they have anything new to add. IIRC, someone early in this thread even said something along the lines of "we seem to be reaching a consensus", but I can't find the reference now. I'd suggest that Chris either mark the PEP as withdrawn, to make it explicit that he has no plans to submit it, or submit it to the SC (ideally with a note for transparency saying that there was no consensus on python-ideas). Nobody is really benefiting from repeating this discussion over and over. Paul ___ 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/VJ26QUYGPOB6NED4NYGCKTOHAWZ7YPS3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 13:13, Brendan Barnwell wrote: > > On 2022-06-17 14:23, Chris Angelico wrote: > > I've just pushed a change to the wording. Let's see if it makes a > > difference. > > > >> I think the PEP would benefit from a fully explicit definition of > >> exactly when and how the late-bound defaults would be evaluated. For > >> instance, by demonstrating an "unrolling" into something paralleling > >> existing Python code. Like: > >> > >> def f(a=>items[0], items=[]): > >> # body > >> > >> is equivalent to: > >> > >> def f(a=FakeDefault, items=[]): > >> a = items[0] > >> # body > > > > That IS in the PEP. Have you read it? > > I read it before your update. Is the version up now the updated one? > I'm guessing it is, because of the remark about "implementations may > choose to do this in two separate passes". > > But I don't see where something like what I showed there is given as a > specification. I do see the "How to Teach This" section, which has an > example similar to mine. But that pretty clearly isn't specifying the > behavior. It still talks about "broadly equivalent" and a "rule of > thumb", which are more ways of saying things other than a fully explicit > and normative specification of the behavior. "Broadly equivalent" is the best you're going to get, though. The entire point of this proposal is that it isn't possible to do a perfect job without language support. So the best you'll get is something with a lot of caveats, or something that is just "basically like this". And your example has the exact same limitations. There's no "FakeDefault" that can behave like that. Is "broadly equivalent" such a bad thing? 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/627P6LIESQ6LJ3M6S5FY7B73FB5DWPY2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 2022-06-17 14:23, Chris Angelico wrote: I've just pushed a change to the wording. Let's see if it makes a difference. I think the PEP would benefit from a fully explicit definition of exactly when and how the late-bound defaults would be evaluated. For instance, by demonstrating an "unrolling" into something paralleling existing Python code. Like: def f(a=>items[0], items=[]): # body is equivalent to: def f(a=FakeDefault, items=[]): a = items[0] # body That IS in the PEP. Have you read it? I read it before your update. Is the version up now the updated one? I'm guessing it is, because of the remark about "implementations may choose to do this in two separate passes". But I don't see where something like what I showed there is given as a specification. I do see the "How to Teach This" section, which has an example similar to mine. But that pretty clearly isn't specifying the behavior. It still talks about "broadly equivalent" and a "rule of thumb", which are more ways of saying things other than a fully explicit and normative specification of the behavior. >> This is all academic to me, however, since even if you did that I still >> wouldn't support the PEP for various more basic reasons that I've >> mentioned in the earlier iteration of this thread. > > And there we have it. People are complaining loudly, but then ALSO > saying that they don't support the proposal anyway. Why are you > bothering to debate this if you've already made your decision? I didn't intend to initially, but as the discussion continued I figured since everyone else was restating their opinions there's no reason I can't do so as well. :-) Also, to avoid people coming back later and saying that some kind of consensus emerged in the second round because no one objected, etc. -- 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/4RALCIBZXTW4GDRM6H5Y6UJNKXTHKJCA/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 12:36, Steven D'Aprano wrote: > I expect Chris will be annoyed at me raising this, but one way of > implementing this would be to introduce a generalised "lazy evaluation" > mechanism, similar to what Haskell does, rather than special-casing > late-bound defaults. Then late-bound defaults just use the same > mechanism, and syntax, as lazily evaluated values anywhere else. Go ahead. Implement it. It actually is NOT sufficient, for a number of reasons, which I have laid out in previous posts. Generic "lazy evaluation" is sufficient to do *some* of what can be done with late-bound argument defaults, but it is not sufficient for everything, unless it is a nightmare that basically involves eval'ing a text string in the surrounding context, with full ability to create and reference any name bindings. Python does not support this concept. > Chris may choose to reject this generalised lazy evaluation idea, but if > so it needs to go into a Rejected Ideas section. Or he may decide that > actually having a generalised lazy evaluation idea is *brilliant* and > much nicer than making defaults a special case. It's an almost completely orthogonal proposal. I used to have a reference to it in the PEP but removed it because it was unhelpful. > This raises another choice: should lazy defaults be evaluated before > entering the body of the function, or at the point where the parameter > is used? Which would be more useful? > > # `defer n=len(items)` > def func(items=[], n=>len(items)): > items.append("Hello") > print(n) > > func() That's one of the problems. Generic lazy evaluation should be processed at some point where the parameter is used, but late-bound defaults are evaluated as the function begins. They are orthogonal. > Printing 1 would require a generalised lazy mechanism, but printing 0 > is independent of the mechanism. As it stands, the PEP requires 0. Which > would be better or more useful? Probably both. If someone wants to propose a generic deferred evaluation feature, I would be happy to discuss it, but it's not a replacement for PEP 671, nor is PEP 671 a replacement for it. > Chris is welcome to push for a particular proposal. That is the purpose > of the PEP process. He is also supposed to give dissenting arguments and > alternatives fair airing in the PEP itself, even if only in a Rejected > Ideas section. > At what point is an unrelated proposal a "rejected idea"? How different does it have to be before it doesn't help to have it in that section? You're welcome to keep on arguing for the sake of arguing, but you're not actually accomplishing anything by it. Especially since you're rehashing the exact same complaints that you raised previously, and which I responded, exactly the same way, at the time. 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/KPJ5TUWMEH4VKPEL2HJSTCJUD22Z5O7A/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, Jun 17, 2022 at 06:32:36AM +0100, Rob Cliffe wrote: > The bar for adding a new hard keyword to Python is very high. Likewise for new syntax. > The suggestion is to add a new keyword to a PEP which absolutely doesn't > need it, *shrug* The match...case statement didn't "need" keywords either, we could have picked symbols instead if we wanted to look like APL. Remember that keywords have advantages as well as disadvantages. Given the existence of community support for keywords, the PEP should make the case that symbols are better in this case. Even if that's only "a majority prefer symbols". > on the grounds that it **might** (**not** would - we can't know > without a spec) give compatibility with some fictional vapourware which > - for all people keep talking about it - hasn't happened in years, isn't > happening (AFAIK nobody is working on it), doesn't have anything > remotely close to even an outline specification (people disagree as to > what it should do), very likely never will happen, and at best won't > happen for years. I think that is broadly accurate. Harsh but fair: nobody has a concrete plan for generalising "defer" keyword would do. It is still vapourware. [...] > def f(x = later -y): > Is that a late-bound default of -y? Bad luck; it's already legal syntax > for an early-bound default of `later` minus `y`. Good catch. > Late-bound defaults are meant to be evaluated at function > call time (and in particular, not some way down in the function body when > the parameter gets used). Not necessarily. I don't recall if this has been raised in this thread before, but it is possible to delay the evaluation of the default value until it is actually needed. I believe that this is how Haskell operates pretty much everywhere. (Haskell experts: do I have that correct?) I expect Chris will be annoyed at me raising this, but one way of implementing this would be to introduce a generalised "lazy evaluation" mechanism, similar to what Haskell does, rather than special-casing late-bound defaults. Then late-bound defaults just use the same mechanism, and syntax, as lazily evaluated values anywhere else. I expect that this is the point that David is making: don't introduce syntax for a special case that will be obsolete in (mumble mumble...) releases. David's point would be stronger if he could point to a concrete plan to introduce lazy evaluation in Python. The Zen of Python gives us some hints: Now is better than never. Although never is often better than *right* now. which possibly suggests that the Zen was written by elves: "I hear it is unwise to seek the council of elves, for they will answer with yes and no." Chris may choose to reject this generalised lazy evaluation idea, but if so it needs to go into a Rejected Ideas section. Or he may decide that actually having a generalised lazy evaluation idea is *brilliant* and much nicer than making defaults a special case. (I think that the Zen has something to say about special cases too.) This raises another choice: should lazy defaults be evaluated before entering the body of the function, or at the point where the parameter is used? Which would be more useful? # `defer n=len(items)` def func(items=[], n=>len(items)): items.append("Hello") print(n) func() Printing 1 would require a generalised lazy mechanism, but printing 0 is independent of the mechanism. As it stands, the PEP requires 0. Which would be better or more useful? I guess Chris will say 0 and David will say 1, but I might be wrong about either of them. One way or the other, these are the sorts of questions that the discussion is supposed to work out, and the PEP is supposed to reference. There are well over 600 emails in this thread and the Steering Council should not be expected to read the whole thing, the PEP is supposed to be an honest and fair summary of alternatives and rejected ideas. Chris is welcome to push for a particular proposal. That is the purpose of the PEP process. He is also supposed to give dissenting arguments and alternatives fair airing in the PEP itself, even if only in a Rejected Ideas section. -- 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/KCDWSAQDA2TSBSLIQ3FBDVI2MN3OPJVD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 06:17, Brendan Barnwell wrote: > > On 2022-06-17 07:53, Chris Angelico wrote: > > On Sat, 18 Jun 2022 at 00:21, Paul Moore wrote: > >> > >> On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > >> > > >> > There are several ways to make this clearly sane. > >> > > >> > # Clearly UnboundLocalError > >> > def frob(n=>len(items), items=>[]): > >> > >> Um, I didn't see that as any more obvious than the original example. I > >> guess I can see it's UnboundLocalError, but honestly that's not > >> obvious to me. > > > > Question: Is this obvious? > > > > def f(): > > x, x[0] = [2], 3 > > print(x) > > > > def boom(): > > x[0], x = 3, [2] > > # raises UnboundLocalError > > Personally, I don't care so much whether the behavior is "obvious" or > even "confusing" as about whether it's defined. Both of those examples > have defined behavior in Python. That's better than having undefined > behavior where either of them might do different things depending on the > implementation. > > > It's unfair to say that I "refuse to assign semantics" as if I'm > > permitting literally any behaviour. All I'm doing is saying that the > > UnboundLocalError is optional, *at this stage*. There have been far > > less-defined semantics that have remained in the language for a long > > time, or cases where something has changed in behaviour over time > > despite not being explicitly stated as implementation-defined. Is this > > legal? > > > > def f(): > > x = 1 > > global x > > > > Does Python mandate whether this is legal or not? If so, how far back > > in Python's history has it been defined? > > If it doesn't mandate it, then it would be better if it did. In my > view, none of your arguments about "some things are undefined" are > actually providing any positive support for the idea that the behavior > in question should remained undefined in the PEP. I've just pushed a change to the wording. Let's see if it makes a difference. > I think the PEP would benefit from a fully explicit definition of > exactly when and how the late-bound defaults would be evaluated. For > instance, by demonstrating an "unrolling" into something paralleling > existing Python code. Like: > > def f(a=>items[0], items=[]): > # body > > is equivalent to: > > def f(a=FakeDefault, items=[]): > a = items[0] > # body That IS in the PEP. Have you read it? > . . . or whatever. I mean, it's up to you as the PEP author to decide > what semantics you want. But I think the PEP should be fully explicit > about the order of evaluation of everything. I don't see any benefit to > leaving it ambiguous. Read the latest version and tell me if it still sounds ambiguous. > This is all academic to me, however, since even if you did that I > still > wouldn't support the PEP for various more basic reasons that I've > mentioned in the earlier iteration of this thread. And there we have it. People are complaining loudly, but then ALSO saying that they don't support the proposal anyway. Why are you bothering to debate this if you've already made your decision? 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/A3WKRWHPTDGF5ZM3PPICY563SDYJ3H4V/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 2022-06-17 07:53, Chris Angelico wrote: On Sat, 18 Jun 2022 at 00:21, Paul Moore wrote: On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > > There are several ways to make this clearly sane. > > # Clearly UnboundLocalError > def frob(n=>len(items), items=>[]): Um, I didn't see that as any more obvious than the original example. I guess I can see it's UnboundLocalError, but honestly that's not obvious to me. Question: Is this obvious? def f(): x, x[0] = [2], 3 print(x) def boom(): x[0], x = 3, [2] # raises UnboundLocalError Personally, I don't care so much whether the behavior is "obvious" or even "confusing" as about whether it's defined. Both of those examples have defined behavior in Python. That's better than having undefined behavior where either of them might do different things depending on the implementation. It's unfair to say that I "refuse to assign semantics" as if I'm permitting literally any behaviour. All I'm doing is saying that the UnboundLocalError is optional, *at this stage*. There have been far less-defined semantics that have remained in the language for a long time, or cases where something has changed in behaviour over time despite not being explicitly stated as implementation-defined. Is this legal? def f(): x = 1 global x Does Python mandate whether this is legal or not? If so, how far back in Python's history has it been defined? If it doesn't mandate it, then it would be better if it did. In my view, none of your arguments about "some things are undefined" are actually providing any positive support for the idea that the behavior in question should remained undefined in the PEP. I think the PEP would benefit from a fully explicit definition of exactly when and how the late-bound defaults would be evaluated. For instance, by demonstrating an "unrolling" into something paralleling existing Python code. Like: def f(a=>items[0], items=[]): # body is equivalent to: def f(a=FakeDefault, items=[]): a = items[0] # body . . . or whatever. I mean, it's up to you as the PEP author to decide what semantics you want. But I think the PEP should be fully explicit about the order of evaluation of everything. I don't see any benefit to leaving it ambiguous. This is all academic to me, however, since even if you did that I still wouldn't support the PEP for various more basic reasons that I've mentioned in the earlier iteration of this thread. -- 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/M36WS6REGOKCUXRLIN2WV2LBU35TAJYR/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 6/17/2022 10:53 AM, Chris Angelico wrote: The only two possible behaviours are: 1) It does the single obvious thing: n defaults to the length of items, and items defaults to an empty tuple. 2) It raises UnboundLocalError if you omit n. ... Would you prefer that I simply mandate that it be permitted, and then a future version of Python changes it to be an exception? Or the other way around? Because I could do that. Maybe it would reduce the arguments. Pun intended, and I am not apologizing for it. A third option would be that it's a syntax error for you to define such a function. This would be my preferred approach. This way, you can always assign semantics in the future. Sure, there are some cases you might want to support with the as-specified undefined behavior, but I don't think that's a good design. If CPython 3.x works a certain way (especially if there's a test for it), you can be sure that other implementations will work the same way, and you can be sure that you can never change the behavior in the future. No amount of "but we said it was undefined" will allow us to change such behavior. It would be like 3.7 saying "yeah, we said dicts are ordered in 3.6 but you shouldn't count on it, so we're going to make them unordered in 3.7". It would just never happen. That all said, I'm still -1 on this PEP, for reasons I won't rehash. Eric ___ 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/XLG4Q2YSKAB5FKEX6EXPTGWOUYQFO3SU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 02:14, Paul Moore wrote: > > On Fri, 17 Jun 2022 at 15:55, Chris Angelico wrote: > > > > On Sat, 18 Jun 2022 at 00:21, Paul Moore wrote: > > > > > > On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > > > > > > > > There are several ways to make this clearly sane. > > > > > > > > # Clearly UnboundLocalError > > > > def frob(n=>len(items), items=>[]): > > > > > > Um, I didn't see that as any more obvious than the original example. I > > > guess I can see it's UnboundLocalError, but honestly that's not > > > obvious to me. > > > > Question: Is this obvious? > > > > def f(): > > x, x[0] = [2], 3 > > print(x) > > > > def boom(): > > x[0], x = 3, [2] > > # raises UnboundLocalError > > No. I'm not sure what point you're trying to make here? The point is that many things can be unobvious, including aspects of important features that we make good use of all the time. But they are consistent, which means that, once you try it and run into a problem, you should be able to see *why* it's a problem. (This particular example is another case of LTR evaluation - or to be more precise, LTR assignment - and while I wouldn't do it in a simple statement like this, I certainly have made use of it in a 'for' loop.) > > I understand that left-to-right evaluation is something that has to be > > learned (and isn't 100% true - operator precedence is a thing too), > > but at very least, if it isn't *obvious*, it should at least be > > *unsurprising* if you then get UnboundLocalError. > > Why? Are you saying I can't be surprised by the details of rules that > I don't often have a need to understand in detail? My point is that "unsurprising", while a much weaker criterion than "obvious", should be quite attainable. If you try the above two pieces of code, you'll quickly find that one of them works and one doesn't, and from the exceptions you get, the rule should be fairly clear. > In case you are, consider that as written, the PEP says > that the *defaults* are evaluated left to right in the function's > runtime scope, but it doesn't say when the parameter names are > introduced in that scope - prior to this PEP there was no need to > define that detail, as nothing could happen before the names were > introduced at the start of the scope. If you accept that > clarification, can you accept that the current text isn't as clear as > it might be? I actually don't accept that clarification, because nothing has changed. At what point in this function do the names get introduced to the scope? def spam(x, y=1, *, z=2): ham = [x, y, z] They are all "introduced", if that term even has meaning, at the very instant that the scope begins to exist. The name 'ham' isn't introduced to the scope at a subsequent point. There are languages that work this way (and it can be very convenient when used correctly), but Python is not one of them. Late-bound defaults do not affect this in any way. A function parameter, like any other local, is local for the entire scope of the function. It doesn't "become local" part way through. Do I need to state this in the PEP? Are there other parts of Python's semantics which need to be restated in the PEP too? Which parts, despite not changing, are now going to be brought into question? > I meant the walrus operator, and that's my point. There's a lot of > not-immediately-obvious interactions here. Even if we don't include > default expressions, I'd argue that the behaviour is non-obvious: > > >>> def f(a=(b:=12)): > ... print(a, b) > ... > >>> f() > 12 12 > >>> b > 12 > > I assume (possibly naïvely) that this is defined in the language spec, > though, as it's existing behaviour. But when you add in default > expressions, you need to be sure that the various interactions are > well-defined. They absolutely are well-defined. Almost certainly not useful, but well-defined. The right hand side of either "a=EXPR" or "a=>EXPR" is simply evaluated as an ordinary expression; the only difference is whether it's evaluated at function definition time and in function definition context, or at function invocation time and in the context of the function itself. > Agreed. Although consider the following: > > >>> def f(a=(b:=12), b=9): > ... print(a, b) > ... > >>> f() > 12 9 > >>> b > 12 Since this is an early-bound default, it can be considered like this: _default = (b:=12) def f(a=None, b=9): if a is None: a = _default print(a, b) And then it should be unsurprising that b becomes 12 in the surrounding scope, paralleling a's default value, and b defaults to 9 in the function's context. > Would > > def frob(n=>len(items:=[]), items=>[1,2]): > ... > > reassign items if n is omitted? Or would it assign the *global* items > and then shadow it with a local for the parameter? Can you point to > the explanation in the PEP that covers this? And even if you can, are > you trying to claim that the behaviour is "obvious"? Since these are both late-bound
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 15:55, Chris Angelico wrote: > > On Sat, 18 Jun 2022 at 00:21, Paul Moore wrote: > > > > On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > > > > > > There are several ways to make this clearly sane. > > > > > > # Clearly UnboundLocalError > > > def frob(n=>len(items), items=>[]): > > > > Um, I didn't see that as any more obvious than the original example. I > > guess I can see it's UnboundLocalError, but honestly that's not > > obvious to me. > > Question: Is this obvious? > > def f(): > x, x[0] = [2], 3 > print(x) > > def boom(): > x[0], x = 3, [2] > # raises UnboundLocalError No. I'm not sure what point you're trying to make here? > I understand that left-to-right evaluation is something that has to be > learned (and isn't 100% true - operator precedence is a thing too), > but at very least, if it isn't *obvious*, it should at least be > *unsurprising* if you then get UnboundLocalError. Why? Are you saying I can't be surprised by the details of rules that I don't often have a need to understand in detail? I fear we're getting off-topic here, though. I'm not arguing that anything here isn't well-defined, just that it's not obvious *to me*. And I'm not even "arguing" that, I'm simply stating it as an observed fact about how I initially reacted to the quoted example. It's you who is stating that the frob case is "clearly" UnboundLocalError, and all I'm saying is that's not "clear" to me, even if it is a consequence of the rules in the PEP. And actually, I could argue that the PEP would benefit from some clarification to make that consequence clearer - but I don't feel that you're likely to be particularly receptive to that statement. In case you are, consider that as written, the PEP says that the *defaults* are evaluated left to right in the function's runtime scope, but it doesn't say when the parameter names are introduced in that scope - prior to this PEP there was no need to define that detail, as nothing could happen before the names were introduced at the start of the scope. If you accept that clarification, can you accept that the current text isn't as clear as it might be? > > > # Clearly correct behaviour > > > def frob(items=[], n=>len(items)): > > > def frob(items=>[], n=>len(items)): > > > > Maybe... I'm not sure I see this as *that* much more obvious, although > > I concede that the left-to-right evaluation rule implies it (it feels > > like a mathematician's use of "obvious" - which quite often isn't ;-)) > > Using assignment expressions in argument defaults is well-defined but > > not necessarily obvious in a similar way (to me, at least). > > When you say "assignment expressions", do you mean "default > expressions", or are you referring to the walrus operator? There's a > lot of other potentially-surprising behaviour if you mix assignment > expressions in with this, because of the difference of scope. It's the > sort of thing that can definitely be figured out, but I would advise > against it. I meant the walrus operator, and that's my point. There's a lot of not-immediately-obvious interactions here. Even if we don't include default expressions, I'd argue that the behaviour is non-obvious: >>> def f(a=(b:=12)): ... print(a, b) ... >>> f() 12 12 >>> b 12 I assume (possibly naïvely) that this is defined in the language spec, though, as it's existing behaviour. But when you add in default expressions, you need to be sure that the various interactions are well-defined. Note that at this point, I'm not even talking about "obvious", simply the bare minimum of "if I write this supposedly legal code, does the PEP explain what it does?" > def frob(items=>[], n=>len(items:=[])): > > This will reassign items to be an empty list if n is omitted. > Obviously that's bad code, but in general, I think assignment > expressions inside default expressions are likely to be very > surprising :) Agreed. Although consider the following: >>> def f(a=(b:=12), b=9): ... print(a, b) ... >>> f() 12 9 >>> b 12 Would def frob(n=>len(items:=[]), items=>[1,2]): ... reassign items if n is omitted? Or would it assign the *global* items and then shadow it with a local for the parameter? Can you point to the explanation in the PEP that covers this? And even if you can, are you trying to claim that the behaviour is "obvious"? > Then let's leave aside the term "obvious" and just go for > "unsurprising". If you write code and get UnboundLocalError, will you > be surprised that it doesn't work? If you write code and it works, > will you be surprised with the result you got? As I noted above, "surprising" is no different. I can easily be surprised by well-defined behaviour. I'm not arguing that there's no explanation for why a particular construct works the way that it does, just that the behaviour may not be intuitive to people even if it is a consequence of the rules. I'm arguing that the behaviour fails an "is this easy to teach" criterion, not "is this
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Chris Angelico writes: > but at very least, if it isn't *obvious*, it should at least be > *unsurprising* if you then get UnboundLocalError. +1 I think this (== "obvious in hindsight") is probably a better criterion than "obvious" (from the definition) when an error *will* be raised. (That's as a general principle. Ie, it doesn't need to be obvious that you will *get* feedback from the system when you do something, but it should be obvious what the feedback means when you *do* get it.) 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/CTTX7MXMYMZEMDGZ3WF7Q5IHMT5JEWWD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sat, 18 Jun 2022 at 00:21, Paul Moore wrote: > > On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > > > > There are several ways to make this clearly sane. > > > > # Clearly UnboundLocalError > > def frob(n=>len(items), items=>[]): > > Um, I didn't see that as any more obvious than the original example. I > guess I can see it's UnboundLocalError, but honestly that's not > obvious to me. Question: Is this obvious? def f(): x, x[0] = [2], 3 print(x) def boom(): x[0], x = 3, [2] # raises UnboundLocalError I understand that left-to-right evaluation is something that has to be learned (and isn't 100% true - operator precedence is a thing too), but at very least, if it isn't *obvious*, it should at least be *unsurprising* if you then get UnboundLocalError. > > # Clearly correct behaviour > > def frob(items=[], n=>len(items)): > > def frob(items=>[], n=>len(items)): > > Maybe... I'm not sure I see this as *that* much more obvious, although > I concede that the left-to-right evaluation rule implies it (it feels > like a mathematician's use of "obvious" - which quite often isn't ;-)) > Using assignment expressions in argument defaults is well-defined but > not necessarily obvious in a similar way (to me, at least). When you say "assignment expressions", do you mean "default expressions", or are you referring to the walrus operator? There's a lot of other potentially-surprising behaviour if you mix assignment expressions in with this, because of the difference of scope. It's the sort of thing that can definitely be figured out, but I would advise against it. def frob(items=>[], n=>len(items:=[])): This will reassign items to be an empty list if n is omitted. Obviously that's bad code, but in general, I think assignment expressions inside default expressions are likely to be very surprising :) > > The only way for it to be confusing is to have => on one argument and > > then = on a subsequent argument, *and* to have the earlier one refer > > to the later one. > > For you, maybe. I assert that the forms above *are* confusing for me. > You're welcome to explain them to me, like you have, and maybe I'll > now remember the logic for the future, but as a data point, I stand by > my statement that these were confusing to me when I encountered them > fresh. Then let's leave aside the term "obvious" and just go for "unsurprising". If you write code and get UnboundLocalError, will you be surprised that it doesn't work? If you write code and it works, will you be surprised with the result you got? Once you learn the basic idea of left-to-right evaluation, it should be possible to try things out and get unsurprising results. That's what I'm hoping for. > Feel free to state that there's not *enough* cases of people > being confused by the semantics to outweigh the benefits, but it feels > to me that there are a few people claiming confusion here, and simply > saying "you shouldn't be confused, it's obvious" isn't really > addressing the point. Part of the problem is that one person seems to think that Python will completely change its behaviour, and he's spreading misinformation. Ignore him, look just at the proposal itself, and tell me if it's still confusing. > > > Even if someone *can* provide an answer, I'd be reluctant to accept > > > that any answer could be described as "intuitive". And "well, don't do > > > that" is just ducking the question - in essentially the same way as > > > "it's implementation defined" does... > > > > But "don't do that" is a perfectly reasonable response to other kinds > > of bad code, like messing up your spacing: > > > > x = 1+2 * 3+4 > > > > Is this intuitive? Some people will think that x should be 21, but the > > actual answer is 11. Python won't stop you from doing this, but style > > guides absolutely should. > > But that's not the same as you leaving the behaviour implementation > defined. In the case of operator precedence, there *is* a well-defined > answer, but the spacing doesn't match that interpretation. That IS the concern when people are talking about what's "intuitive" though. > But in the case of > > frob(n=>len(items), items=()) > > you're refusing to give a well-defined semantics, and then saying that > people shouldn't do that. But unlike spacing of expressions, the order > of arguments is *important* - it is part of the API of frob that the > first positional argument is n, so "just swap the arguments" is a > semantic change. So how should people get the ("obvious") intended > behaviour? Abandon the new syntax and go back to using None as a > default? That seems a shame, given that (as I understand it) your > reference implementation works exactly as I'd want. The only two possible behaviours are: 1) It does the single obvious thing: n defaults to the length of items, and items defaults to an empty tuple. 2) It raises UnboundLocalError if you omit n. To be quite honest, I can't think of any non-toy examples where the defaults would
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 14:15, Chris Angelico wrote: > > There are several ways to make this clearly sane. > > # Clearly UnboundLocalError > def frob(n=>len(items), items=>[]): Um, I didn't see that as any more obvious than the original example. I guess I can see it's UnboundLocalError, but honestly that's not obvious to me. > # Clearly correct behaviour > def frob(items=[], n=>len(items)): > def frob(items=>[], n=>len(items)): Maybe... I'm not sure I see this as *that* much more obvious, although I concede that the left-to-right evaluation rule implies it (it feels like a mathematician's use of "obvious" - which quite often isn't ;-)) Using assignment expressions in argument defaults is well-defined but not necessarily obvious in a similar way (to me, at least). > The only way for it to be confusing is to have => on one argument and > then = on a subsequent argument, *and* to have the earlier one refer > to the later one. For you, maybe. I assert that the forms above *are* confusing for me. You're welcome to explain them to me, like you have, and maybe I'll now remember the logic for the future, but as a data point, I stand by my statement that these were confusing to me when I encountered them fresh. Feel free to state that there's not *enough* cases of people being confused by the semantics to outweigh the benefits, but it feels to me that there are a few people claiming confusion here, and simply saying "you shouldn't be confused, it's obvious" isn't really addressing the point. > > Even if someone *can* provide an answer, I'd be reluctant to accept > > that any answer could be described as "intuitive". And "well, don't do > > that" is just ducking the question - in essentially the same way as > > "it's implementation defined" does... > > But "don't do that" is a perfectly reasonable response to other kinds > of bad code, like messing up your spacing: > > x = 1+2 * 3+4 > > Is this intuitive? Some people will think that x should be 21, but the > actual answer is 11. Python won't stop you from doing this, but style > guides absolutely should. But that's not the same as you leaving the behaviour implementation defined. In the case of operator precedence, there *is* a well-defined answer, but the spacing doesn't match that interpretation. But in the case of frob(n=>len(items), items=()) you're refusing to give a well-defined semantics, and then saying that people shouldn't do that. But unlike spacing of expressions, the order of arguments is *important* - it is part of the API of frob that the first positional argument is n, so "just swap the arguments" is a semantic change. So how should people get the ("obvious") intended behaviour? Abandon the new syntax and go back to using None as a default? That seems a shame, given that (as I understand it) your reference implementation works exactly as I'd want. > In the same way, I would strongly recommend that style guides frown > upon referring to arguments later in the parameter list, even if it > happens to be legal. I'm just not mandating that the language check > for this and artificially block it. You're not *just* recommending this for style guides, you're also explicitly stating that you refuse to assign semantics to it. Anyway, all of this is just my opinion. I'm not trying to persuade you that you're wrong, just to point out that others see things differently. It's up to you what you do with that information. Change the PEP or don't, put it back into deferred status or submit it. I'm not the decision maker here, just a community member whose feedback will (hopefully) be considered by the SC when making the decision if the PEP comes to them. Paul ___ 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/VGXSX6GDV46J7JUVOWHZPL2CO6SZYUER/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Steve D'Aprano wrote of an incompleteness in this PEP This is not just some minor, trivial implementation issue, it cuts right > to the core of this feature's semantics [...] For comparison, please look at the PEP for the statistics module. Steve wrote both PEP and the standard library module. In my opinion the PEP is deficient in its description of core semantics, and I don't see a reference implementation prior to acceptance. https://peps.python.org/pep-0450/ Of course, that was nearly 10 years ago. The recently discussed problems with type conversion in the statistics module together with what's missing in PEP 450 together support Steve's request that the PEP discussed in this thread be improved, so that we better avoid future problems. -- 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/Z435E4ZW3GFPNKH5JQFELVWX3J27IG7I/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 23:05, Paul Moore wrote: > > On Fri, 17 Jun 2022 at 13:54, Andrew Jaffe wrote: > > > > Is there a *reason* why you are leaving this unspecified? To put it more > > baldly, is there any reason (e.g., difficulty of parsing?) why allowing > > these "forward" references should *not* be allowed? It seems that > > "n=>len(items), items=[]" might be an important use case. > > Am I right in thinking the key issue here is that => is *not* used for > "items"? So > > def frob(n=>len(items), items=[]): > print(n) > items.append(1) > > gets very complicated to reason about. What does this print? There are several ways to make this clearly sane. # Clearly UnboundLocalError def frob(n=>len(items), items=>[]): # Clearly correct behaviour def frob(items=[], n=>len(items)): def frob(items=>[], n=>len(items)): The only way for it to be confusing is to have => on one argument and then = on a subsequent argument, *and* to have the earlier one refer to the later one. > Even if someone *can* provide an answer, I'd be reluctant to accept > that any answer could be described as "intuitive". And "well, don't do > that" is just ducking the question - in essentially the same way as > "it's implementation defined" does... But "don't do that" is a perfectly reasonable response to other kinds of bad code, like messing up your spacing: x = 1+2 * 3+4 Is this intuitive? Some people will think that x should be 21, but the actual answer is 11. Python won't stop you from doing this, but style guides absolutely should. In the same way, I would strongly recommend that style guides frown upon referring to arguments later in the parameter list, even if it happens to be legal. I'm just not mandating that the language check for this and artificially block it. 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/HDOUSXXYIJVAHK6JOQVTSQDJTLM3ROIP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 22:55, Andrew Jaffe wrote: > > First, let me state that I am in favour of the proposal (although still > mildle prefer the ":=" spelling). > > On 17/06/2022 13:33, Chris Angelico wrote: > > On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano wrote: > >> > >> If we have: > >> ``` > >> items = ['spam', 'eggs'] > >> def frob(n=>len(items), items=[]): > >> print(n) > >> ``` > >> we cannot even tell whether `frob()` will print 0 or 2 or raise an > >> exception. > > > > It will either print 0 or raise UnboundLocalError. There is no > > circumstance in which it will legally print 2. > > > >> Under the PEP though, this behaviour is underspecified. The PEP > >> describes this case as implementation dependent. Any of the following > >> behaviours would be legal when `frob()` is called: > >> > >> * n=>len(items) evaluates the parameter `items`, *after* it gets > >>bound to the default of [], and so n=0 (that is, it has the same > >>semantics as the status quo); > > > > Yes, this is legal. > > > >> * n=>len(items) evaluates the parameter `items`, but it isn't bound > >>to a value yet (because `items` occurs to the right of n), and so > >>evaluating the default raises (presumably) UnboundLocalError; > > > > Yes, this is legal. > > > >> * n=>len(items) evaluates the variable items from the surrounding scope, > >>and so evaluates to n=2; if no such variable exists, it will presumably > >>raise NameError. > > > > No, this makes no sense whatsoever. In Python, a parameter is > > (effectively) assigned to within the function, and therefore *any* > > reference to it *must* refer to the local, not to any surrounding > > scope. Late-bound defaults do not change this fundamental. > > I understand this is unambiguous, but it is nonetheless potentially > confusing: normal, immediate-evaluation arguments do, of course, have > access to enclosing scope, and so one might be led to believe that this > is still possible. That's because immediate-evaluation is like this: _default = SOME_EXPRESSION def func(n=None): if n is None: n = _default Whereas late evaluation is like this: def func(n=None): if n is None: n = SOME_EXPRESSION Unfortunately, there's not going to be any way to resolve this. The entire point of this feature is to be able to do things that can't be done with early evaluation, and that includes referring to other arguments, so it fundamentally has to be done in the function's scope. Maybe it would have been convenient for Python to define that function defaults are *always* evaluated in the function's scope, but (a) that ship has well and truly sailed, and (b) I'm not sure that that would be better anyway - the current behaviour lets you do an easy snapshot by writing something like "i=i", so it has the same name on the inside that it has on the outside. For the most part, it's not a problem; scopes are nested, so you can happily refer to a name in an enclosing scope. Exceptions include names that are shadowed, class-level names (but you'll usually be able to write "self.X" or "cls.X" so it's just a difference of spelling), and possibly some quirks of closures, although most of those are a consequence of timing rather than scoping. > >> With the behaviour unspecified, we can't predict whether the above > >> frob() example is legal or what it will do if it is. It could vary not > >> only between CPython and other Pythons, but from one version of CPython > >> and another. > > > > That is correct. This issue ONLY happens if a late-bound default > > refers to an early-bound argument that comes to the right of it in the > > argument list, and the ONLY possible results are UnboundLocalError and > > getting the value. > > Is there a *reason* why you are leaving this unspecified? To put it more > baldly, is there any reason (e.g., difficulty of parsing?) why allowing > these "forward" references should *not* be allowed? It seems that > "n=>len(items), items=[]" might be an important use case. > Yes. The alternative is that I make it "reference-implementation-defined", and I've seen so much of that that I don't want to lock that in. Just because the way I happen to have implemented it allows for the late-bound defaults to refer to early-bound arguments to their right, I don't want to lock the language into behaving that way forever; conversely, I don't want to have a non-compliant reference implementation based on a definition of "all arguments are assigned left to right", which is much cleaner and simpler to describe, but a lot harder to implement. I want the language to be open to the cleaner definition, while permitting the "arguments are assigned left to right in two stages" implementation as well. That's the only distinction though. And if you simply place all late-bound defaults to the right of all early-bound defaults, there won't be any problem, ever. ChrisA ___ Python-ideas mailing list --
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 13:54, Andrew Jaffe wrote: > > Is there a *reason* why you are leaving this unspecified? To put it more > baldly, is there any reason (e.g., difficulty of parsing?) why allowing > these "forward" references should *not* be allowed? It seems that > "n=>len(items), items=[]" might be an important use case. Am I right in thinking the key issue here is that => is *not* used for "items"? So def frob(n=>len(items), items=[]): print(n) items.append(1) gets very complicated to reason about. What does this print? frob() frob() frob(items=[1,2,3,4,5]) frob(3, []) frob() frob(3) frob() Even if someone *can* provide an answer, I'd be reluctant to accept that any answer could be described as "intuitive". And "well, don't do that" is just ducking the question - in essentially the same way as "it's implementation defined" does... Paul ___ 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/XAUNUGXYCCFU2OXUORMKRPHSRQO5HTX3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
OT: On Fri, Jun 17, 2022 at 7:35 AM Rob Cliffe > > def for(bar=[] later, baz=timenow() later, bam=inc(baz) later): > Not only is the second one longer and repetitious, it adds more **words**. > People are used to distinguishing between words and symbols and do it > easily. > You have just articulated why I find type annotations so hard to read. Back OT: add annotations to the examples, and it gets worse. I like it or not, I suspect annotations are becoming “standard” -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/XFT6PXP4SCH5FO3WXAGEIMKOP6PZMIW6/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
First, let me state that I am in favour of the proposal (although still mildle prefer the ":=" spelling). On 17/06/2022 13:33, Chris Angelico wrote: On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano wrote: If we have: ``` items = ['spam', 'eggs'] def frob(n=>len(items), items=[]): print(n) ``` we cannot even tell whether `frob()` will print 0 or 2 or raise an exception. It will either print 0 or raise UnboundLocalError. There is no circumstance in which it will legally print 2. Under the PEP though, this behaviour is underspecified. The PEP describes this case as implementation dependent. Any of the following behaviours would be legal when `frob()` is called: * n=>len(items) evaluates the parameter `items`, *after* it gets bound to the default of [], and so n=0 (that is, it has the same semantics as the status quo); Yes, this is legal. * n=>len(items) evaluates the parameter `items`, but it isn't bound to a value yet (because `items` occurs to the right of n), and so evaluating the default raises (presumably) UnboundLocalError; Yes, this is legal. * n=>len(items) evaluates the variable items from the surrounding scope, and so evaluates to n=2; if no such variable exists, it will presumably raise NameError. No, this makes no sense whatsoever. In Python, a parameter is (effectively) assigned to within the function, and therefore *any* reference to it *must* refer to the local, not to any surrounding scope. Late-bound defaults do not change this fundamental. I understand this is unambiguous, but it is nonetheless potentially confusing: normal, immediate-evaluation arguments do, of course, have access to enclosing scope, and so one might be led to believe that this is still possible. With the behaviour unspecified, we can't predict whether the above frob() example is legal or what it will do if it is. It could vary not only between CPython and other Pythons, but from one version of CPython and another. That is correct. This issue ONLY happens if a late-bound default refers to an early-bound argument that comes to the right of it in the argument list, and the ONLY possible results are UnboundLocalError and getting the value. Is there a *reason* why you are leaving this unspecified? To put it more baldly, is there any reason (e.g., difficulty of parsing?) why allowing these "forward" references should *not* be allowed? It seems that "n=>len(items), items=[]" might be an important use case. Andrew ___ 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/TJSC55W4PUBNNOVVEUQHH5YMEWGPAP4S/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano wrote: > > On Thu, Jun 16, 2022 at 08:31:19AM +1000, Chris Angelico wrote: > > On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano wrote: > > > > Under the Specification section, the PEP explicitly refers to > > > behaviour which "may fail, may succeed", and different behaviour which > > > is "Highly likely to give an error", and states "Using names of later > > > arguments should not be relied upon, and while this MAY work in some > > > Python implementations, it should be considered dubious". > > > > > > So, yes, the PEP *punts* on the semantics of the feature, explicitly > > > leaving the specification implementation-dependent. > > > > > > > One very very specific aspect of it is left undefined. Are you really > > bothered by that? > > Yes. > > This is not just some minor, trivial implementation issue, it cuts right > to the core of this feature's semantics: > > * Which arguments can a late-bound parameter access? Definitely those that come before it. Potentially some of those that come after it, but I'm not mandating that. > * When the late-bound default is evaluated, what is the name resolution > rule? (Which variables from which scopes will be seen?) Exactly the same as any other code executed in the function. I really don't see why this is so surprising to you; it is *exactly the normal behaviour of Python code*. > These are fundamental details related to the meaning of code, not relatively > minor details such as the timing of when a destructor will run. They're exactly as fundamental, actually. The 'with' statement was added to the language specifically because it was critically important to clean things up in ways that CPython does, but Python does not guarantee. In my reference implementation, more is available than the PEP guarantees. That's all. > If we have: > > ``` > items = ['spam', 'eggs'] > def frob(n=>len(items), items=[]): > print(n) > > ``` > > we cannot even tell whether `frob()` will print 0 or 2 or raise an > exception. It will either print 0 or raise UnboundLocalError. There is no circumstance in which it will legally print 2. > I described this underspecification as a weakness of the PEP. As I said > at the time, that was my opinion. As the PEP author, of course it is > your perogative to leave the semantics of this feature underspecified, > hoping that the Steering Council will be happy with implementation- > dependent semantics. It's a lot less implementation-dependent than you seem to think. > For the benefit of other people reading this, in case it isn't clear, > let me try to explain what the issue is. > > When late-bound defaults are simulated with the `is None` trick, we > write: > > ``` > def frob(n=None, items=[]): > # If we enter the body of the function, > # items is guaranteed to have a value. > if n is None: > n = len(items) > print(n) > ``` > > and there is never any doubt about the scoping rules for `len(items)`. > It always refers to the parameter `items`, never to the variable in the > surrounding scope, and because that parameter is guaranteed to be bound > to a value, so the simulated default `len(items)` cannot fail with > NameError. We can reason about the code's meaning very easily. This is exactly the same. I don't understand what's confusing here. > If we want "real" late-bound defaults to match that behaviour, > `n=>len(items)` must evaluate `len(items)` *after* items is bound > to a value, even though items occurs to the right of n. Yes, and the ONLY part that is underspecified is the order. It is perfectly legal for it to be implemented in either of these ways: def frob(): n = len(items) items = [] def frob(): items = [] n = len(items) And I would consider code that depends on specifically one or the other to be bad code, just like code that depends on __del__ methods being called. What wording could I add to the PEP to make this more obvious? > Under the PEP though, this behaviour is underspecified. The PEP > describes this case as implementation dependent. Any of the following > behaviours would be legal when `frob()` is called: > > * n=>len(items) evaluates the parameter `items`, *after* it gets > bound to the default of [], and so n=0 (that is, it has the same > semantics as the status quo); Yes, this is legal. > * n=>len(items) evaluates the parameter `items`, but it isn't bound > to a value yet (because `items` occurs to the right of n), and so > evaluating the default raises (presumably) UnboundLocalError; Yes, this is legal. > * n=>len(items) evaluates the variable items from the surrounding scope, > and so evaluates to n=2; if no such variable exists, it will presumably > raise NameError. No, this makes no sense whatsoever. In Python, a parameter is (effectively) assigned to within the function, and therefore *any* reference to it *must* refer to the local, not to any surrounding scope. Late-bound defaults do not change
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Thu, Jun 16, 2022 at 08:31:19AM +1000, Chris Angelico wrote: > On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano wrote: > > Under the Specification section, the PEP explicitly refers to > > behaviour which "may fail, may succeed", and different behaviour which > > is "Highly likely to give an error", and states "Using names of later > > arguments should not be relied upon, and while this MAY work in some > > Python implementations, it should be considered dubious". > > > > So, yes, the PEP *punts* on the semantics of the feature, explicitly > > leaving the specification implementation-dependent. > > > > One very very specific aspect of it is left undefined. Are you really > bothered by that? Yes. This is not just some minor, trivial implementation issue, it cuts right to the core of this feature's semantics: * Which arguments can a late-bound parameter access? * When the late-bound default is evaluated, what is the name resolution rule? (Which variables from which scopes will be seen?) These are fundamental details related to the meaning of code, not relatively minor details such as the timing of when a destructor will run. If we have: ``` items = ['spam', 'eggs'] def frob(n=>len(items), items=[]): print(n) ``` we cannot even tell whether `frob()` will print 0 or 2 or raise an exception. I described this underspecification as a weakness of the PEP. As I said at the time, that was my opinion. As the PEP author, of course it is your perogative to leave the semantics of this feature underspecified, hoping that the Steering Council will be happy with implementation- dependent semantics. For the benefit of other people reading this, in case it isn't clear, let me try to explain what the issue is. When late-bound defaults are simulated with the `is None` trick, we write: ``` def frob(n=None, items=[]): # If we enter the body of the function, # items is guaranteed to have a value. if n is None: n = len(items) print(n) ``` and there is never any doubt about the scoping rules for `len(items)`. It always refers to the parameter `items`, never to the variable in the surrounding scope, and because that parameter is guaranteed to be bound to a value, so the simulated default `len(items)` cannot fail with NameError. We can reason about the code's meaning very easily. If we want "real" late-bound defaults to match that behaviour, `n=>len(items)` must evaluate `len(items)` *after* items is bound to a value, even though items occurs to the right of n. Under the PEP though, this behaviour is underspecified. The PEP describes this case as implementation dependent. Any of the following behaviours would be legal when `frob()` is called: * n=>len(items) evaluates the parameter `items`, *after* it gets bound to the default of [], and so n=0 (that is, it has the same semantics as the status quo); * n=>len(items) evaluates the parameter `items`, but it isn't bound to a value yet (because `items` occurs to the right of n), and so evaluating the default raises (presumably) UnboundLocalError; * n=>len(items) evaluates the variable items from the surrounding scope, and so evaluates to n=2; if no such variable exists, it will presumably raise NameError. With the behaviour unspecified, we can't predict whether the above frob() example is legal or what it will do if it is. It could vary not only between CPython and other Pythons, but from one version of CPython and another. -- 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/JDZB3TVVNJIZD4X7QJ35D2PLWLYCN5DJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Fri, Jun 17, 2022 at 02:36:48AM -, Steve Jorgensen wrote: > Is there anything that I can do, as a random Python user to help move > this to the next stage? If you think the PEP is as complete and persuasive as possible right now, you can offer moral support and encouragement. Or you can suggest some improvements, and see whether the PEP author agrees. It is up to the PEP author to decide whether, in his opinion, the PEP is sufficiently complete to move forward, or whether it needs more work. Other options include leaving it deferred/incomplete, to withdraw it, or solicit for somebody to take it over. If the PEP author abandons it, you could ask to take it over, or you could write your own competing PEP as an alternative. If the author decides to move forward, he needs to ask for a core dev to sponsor it. Assuming he gets one, that will start the next round of debate, followed by a request to the Steering Council to make a decision whether to accept it as is, demand some changes, or reject it. -- 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/QPS6IIXH6M3C545ZEQ6ALKOECMUUF5XP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 15/06/2022 23:01, Steven D'Aprano wrote: On Wed, Jun 15, 2022 at 01:58:28PM +0100, Rob Cliffe via Python-ideas wrote: Please. This has been many times by several people already. No-one is going to change their mind on this by now. There's no point in rehashing it and adding noise to the thread. Rob, there's no rule that only "people who support this PEP" are allowed to comment. If it is okay for you to say you like this PEP even more now than previously, it is okay for David to say that his opinion hasn't changed. Of course I wasn't saying that some people aren't allowed to comment. What I was objecting to was the rehashing of old arguments which have already been done to death. I refrained, at the time, from offering counter-arguments, because those have been done to death too. Especially since David even pointed out one potential change which might lead him to support the PEP, or at least shift to "neutral". You are quite right Steven, and perhaps I was too hasty, didn't pay enough attention to David's suggestion, and failed to address it. Well, let me address it now. I am afraid I can't do so without repeating some of my old arguments and thus doing exactly what I asked David not to do, but he has made a suggestion and it merits being answered. Thank you for contributing to this thread, David. "I believe a general "deferred computation" mechanism is useful, but that one limited to the context of function parameters does more harm than good is scoped narrowly to that single use. I keyword version might bridge that gap by introducing "later" or "defer" or "delay" in a narrow context, but not foreclosing its later use more broadly." [DM] The bar for adding a new hard keyword to Python is very high. The suggestion is to add a new keyword to a PEP which absolutely doesn't need it, on the grounds that it **might** (**not** would - we can't know without a spec) give compatibility with some fictional vapourware which - for all people keep talking about it - hasn't happened in years, isn't happening (AFAIK nobody is working on it), doesn't have anything remotely close to even an outline specification (people disagree as to what it should do), very likely never will happen, and at best won't happen for years. And if it does, what's the **worst** that could happen? We would have two ways of writing the same thing! Terrible! Well, we already have that in effect (yes, I know they generate different compiled code): x = 42 (x := 42) {} dict() # similarly for list, tuple and I expect there are a host of other examples I can't bring to mind at the moment, and the sky hasn't fallen. I'm sorry, but if that's what it takes to make David or anyone else less opposed to the PEP, it ain't worth it. Not remotely close. So It could be a soft keyword, you say? OK, AFAICS that could work. But let me note in passing that if we consider 4 possible syntaxes: def func(later parm = default): # Number 1 def func(parm later = default): # Number 2 def func(parm = later default): # Number 3 def func(parm = default later): # Number 4 Number 3, which some might find the most attractive, won't work. Consider: def f(x = later -y): Is that a late-bound default of -y? Bad luck; it's already legal syntax for an early-bound default of `later` minus `y`. AFAICS the others are possible. If you have some other syntax in mind, David, please specify. But (and AFAIK this has not been said before) let's think about this supposed "consistency". Let's suppose we have a bright-and-shiny, up-and-running delayed evaluation scheme. I imagine (and again, if this is not what you have in mind, David, please specify) it would allow you to write something like x = expression later which would assign to x some entity, a "deferred evaluation object" (DEO), probably containing a code object, which would allow the expression to be evaluated at some future time (and possibly in some different scope, but let's not go there now). On the principle of least surprise, one would want "expression later" to be a Python expression, and to behave as far as possible in the same way in different contexts. So you could write stuff like x = y = expression later someTuple = (expression1 later, expression2 later) and so on. (It's not relevant to my point, but I can't imagine wanting syntax like Number 1 or Number 2 above: later x = expression # value of expression to be calculated and assigned to x at some future time What would these mean, if legal: later x = y = expression x = later y = expression later x = later y = expression ). But when I use that same syntax *in a function signature*: def f(x = expression later): and then call f(), I do **not** (in most cases) want the default value of x to be a DEO. I want it evaluated NOW, at function call time. So where is the consistency? There isn't any. It's a myth. Of
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On 17/06/2022 04:23, David Mertz, Ph.D. wrote: I've been scolded that I'm not allowed to post unless I support the PEP. Please do not misrepresent me. That is NOT what I said. Rob Cliffe Nonetheless, I reiterate that I oppose it. There is no "preponderance" of support, but perhaps a slim majority of the small number who have commented (5 vs 3, I think). On Thu, Jun 16, 2022, 10:38 PM Steve Jorgensen wrote: Is there anything that I can do, as a random Python user to help move this to the next stage? I'm happy to go along with whatever the preponderance of responses here seem to think in terms of which syntax choice is best. Although I have a slight preference, all of the options seem decent to me. I am definitely in favor of having the PEP accepted and implemented. ___ 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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/ Code of Conduct: http://python.org/psf/codeofconduct/ ___ 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/73JW7MNPPHIOCMOFCTD34Z5YMK7ESNS5/ 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/2NDF7ER6MJWDHAFQNI7RP7L322OTXJZU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I've been scolded that I'm not allowed to post unless I support the PEP. Nonetheless, I reiterate that I oppose it. There is no "preponderance" of support, but perhaps a slim majority of the small number who have commented (5 vs 3, I think). On Thu, Jun 16, 2022, 10:38 PM Steve Jorgensen wrote: > Is there anything that I can do, as a random Python user to help move this > to the next stage? I'm happy to go along with whatever the preponderance of > responses here seem to think in terms of which syntax choice is best. > Although I have a slight preference, all of the options seem decent to me. > > I am definitely in favor of having the PEP accepted and implemented. > ___ > 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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/ > 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/73JW7MNPPHIOCMOFCTD34Z5YMK7ESNS5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Is there anything that I can do, as a random Python user to help move this to the next stage? I'm happy to go along with whatever the preponderance of responses here seem to think in terms of which syntax choice is best. Although I have a slight preference, all of the options seem decent to me. I am definitely in favor of having the PEP accepted and implemented. ___ 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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano wrote: > > On Thu, Jun 16, 2022 at 12:02:04AM +1000, Chris Angelico wrote: > > On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano wrote: > > > There's no consensus that this feature is worth the added complexity, or > > > even what the semantics are. The PEP punts on the semantics, saying that > > > the behaviour may vary across implementations. > > > > Excuse me? I left one or two things open-ended, where they're bad code > > and I'm not going to lock the language into supporting them just > > because the reference implementation happens to be able to, but > > "punts"? That's a bit much. The semantics are QUITE specific. > > Under the Specification section, the PEP explicitly refers to > behaviour which "may fail, may succeed", and different behaviour which > is "Highly likely to give an error", and states "Using names of later > arguments should not be relied upon, and while this MAY work in some > Python implementations, it should be considered dubious". > > So, yes, the PEP *punts* on the semantics of the feature, explicitly > leaving the specification implementation-dependent. > One very very specific aspect of it is left undefined. Are you really bothered by that? I don't understand how you can dare to write a single line of code, given how many other things are actually not specified. Have you ever written a __del__ method? Python *does not guarantee* when it will be called. Wow! Python is hopelessly implementation-dependent, there's no WAY this should ever be used! And then you take this tiny point where I left it open to implementers to choose, and you say that the PEP "punts on the semantics" as if the entire specification is in doubt. I'm trying as hard as I can to believe that you're arguing in good faith, but it's getting less and less plausible. 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/JQI3QMNWNFMNS5XICJSX5NMEF52IHWBR/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Thu, Jun 16, 2022 at 12:02:04AM +1000, Chris Angelico wrote: > On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano wrote: > > There's no consensus that this feature is worth the added complexity, or > > even what the semantics are. The PEP punts on the semantics, saying that > > the behaviour may vary across implementations. > > Excuse me? I left one or two things open-ended, where they're bad code > and I'm not going to lock the language into supporting them just > because the reference implementation happens to be able to, but > "punts"? That's a bit much. The semantics are QUITE specific. Under the Specification section, the PEP explicitly refers to behaviour which "may fail, may succeed", and different behaviour which is "Highly likely to give an error", and states "Using names of later arguments should not be relied upon, and while this MAY work in some Python implementations, it should be considered dubious". So, yes, the PEP *punts* on the semantics of the feature, explicitly leaving the specification implementation-dependent. > > There's no consensus on the syntax, which may not matter, the Steering > > Council can make the final decision if necessary. But with at least four > > options in the PEP it would be good to narrow it down a bit. No soft > > keywords have been considered. > > """Choice of spelling. While this document specifies a single syntax > `name=>expression`...""" > > The PEP specifies *one* option. The part of the sentence you replaced with an ellipsis says "alternate spellings are similarly plausible." The very next sentence says "Open for consideration are the following" and a couple of paragraphs later you even explicitly refer to a second proof of concept implemention. The PEP has a preferred syntax, as is its right, but it lists three alternatives still under consideration. -- 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/23N2VZFHWOLR6ZKFMOU26QXFSFHSY7I4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, Jun 15, 2022 at 01:58:28PM +0100, Rob Cliffe via Python-ideas wrote: > Please. This has been many times by several people already. No-one is > going to change their mind on this by now. There's no point in > rehashing it and adding noise to the thread. Rob, there's no rule that only "people who support this PEP" are allowed to comment. If it is okay for you to say you like this PEP even more now than previously, it is okay for David to say that his opinion hasn't changed. Especially since David even pointed out one potential change which might lead him to support the PEP, or at least shift to "neutral". -- 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/42PANNPF4YTDOQQ76BWUPFRVV7YGBUAQ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano wrote: > There's no consensus that this feature is worth the added complexity, or > even what the semantics are. The PEP punts on the semantics, saying that > the behaviour may vary across implementations. Excuse me? I left one or two things open-ended, where they're bad code and I'm not going to lock the language into supporting them just because the reference implementation happens to be able to, but "punts"? That's a bit much. The semantics are QUITE specific. > There's no consensus on the syntax, which may not matter, the Steering > Council can make the final decision if necessary. But with at least four > options in the PEP it would be good to narrow it down a bit. No soft > keywords have been considered. """Choice of spelling. While this document specifies a single syntax `name=>expression`...""" The PEP specifies *one* option. > In my opinion, there are weaknesses in the PEP: > > - lack of any reference to previous discussions; > > - no attempt to gather feedback from other forums; > > - no review of languages that offer choice of early or late binding; > > - little attempt to justify why this is better than the status quo; the > PEP seems to take the position that it is self-evident that Python > needs this feature, rather than being a balanced document setting out > both pros and cons; > > - little or no attempt in the PEP to answer objections; > > - examples are all chosen to show the feature in the best possible > light, rather than to show both the good and bad; (e.g. no examples > show the parameter with annotations) > > - failure to acknowledge that at least one of the suggested syntaxes > is visually ambiguous with existing syntax. > > E.g. this would be legal with the PEP's second choice of spelling: > > def func(spam, eggs:=(x:=spam)): > > Even if the parser can distinguish the two uses of `:=` there, its > awfully cryptic. In and of itself, that's not necessarily a fatal flaw > (e.g. slicing) but the benefits have to outweigh the negatives, and the > PEP should be a balanced discussion of both. And that's not the recommended syntax anyway. Please, if you're going to criticize the document, *at least* have the decency to check your facts. You are the PRIMARY reason that I gave up pushing this earlier. I am within a very short span of blocking you in my mail client and refusing to respond to your emails, because it feels like a massive waste of my time trying. 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/Z7JKPTKL2DVDLJ6MCZWOHF6NWLKZ56O4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, 15 Jun 2022 at 14:04, Rob Cliffe via Python-ideas wrote: > > Please. This has been many times by several people already. No-one is going > to change their mind on this by now. There's no point in rehashing it and > adding noise to the thread. To be fair, the only real point in re-opening the discussion at all is to determine if anyone has changed their mind. That said, IMO it's unlikely that enough time has passed for that to have happened, so it's unlikely that anything productive will come from this new thread. Paul ___ 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/KITPPSXCDQBTI3HJCZHLFEAU2RLJOY4W/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Please. This has been many times by several people already. No-one is going to change their mind on this by now. There's no point in rehashing it and adding noise to the thread. Best wishes Rob Cliffe On 15/06/2022 13:43, David Mertz, Ph.D. wrote: As well as all the matters Steven raises, I continue to dislike the proposal for the same reason I did on earlier rounds. I believe a general "deferred computation" mechanism is useful, but that one limited to the context of function parameters does more harm than good is scoped narrowly to that single use. I keyword version might bridge that gap by introducing "later" or "defer" or "delay" in a narrow context, but not foreclosing its later use more broadly. On Wed, Jun 15, 2022 at 8:38 AM Steven D'Aprano wrote: On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via Python-ideas wrote: > I used to prefer `:=` but coming back to this topic after a long > interval I am happy with `=>` and perhaps I even like it more, Chris. > The PEP status is "Draft". What are the chances of something happening > any time soon, i.e. the PEP being considered by the Steering Committee? There's no Sponsor, so it isn't being considered by the SC. That much is objectively true. Beyond that, the following is all my personal opinion, and should not be taken as definitive or official in any way. Importantly, I have *not* read back through the entire thread to refresh my memory. However, I have re-read the PEP in detail. There's no consensus that this feature is worth the added complexity, or even what the semantics are. The PEP punts on the semantics, saying that the behaviour may vary across implementations. There's no consensus on the syntax, which may not matter, the Steering Council can make the final decision if necessary. But with at least four options in the PEP it would be good to narrow it down a bit. No soft keywords have been considered. In my opinion, there are weaknesses in the PEP: - lack of any reference to previous discussions; - no attempt to gather feedback from other forums; - no review of languages that offer choice of early or late binding; - little attempt to justify why this is better than the status quo; the PEP seems to take the position that it is self-evident that Python needs this feature, rather than being a balanced document setting out both pros and cons; - little or no attempt in the PEP to answer objections; - examples are all chosen to show the feature in the best possible light, rather than to show both the good and bad; (e.g. no examples show the parameter with annotations) - failure to acknowledge that at least one of the suggested syntaxes is visually ambiguous with existing syntax. E.g. this would be legal with the PEP's second choice of spelling: def func(spam, eggs:=(x:=spam)): Even if the parser can distinguish the two uses of `:=` there, its awfully cryptic. In and of itself, that's not necessarily a fatal flaw (e.g. slicing) but the benefits have to outweigh the negatives, and the PEP should be a balanced discussion of both. -- 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/V5K2JFT44A57ZXV2GS3OS6MQW2YKXMQN/ Code of Conduct: http://python.org/psf/codeofconduct/ -- 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 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/V2WTEHWFOL5LTW76QVGYMAGSNUAHOR6R/ 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/HRHMR4HEMI3JCNMDYMEJ42PFDWXD7346/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
As well as all the matters Steven raises, I continue to dislike the proposal for the same reason I did on earlier rounds. I believe a general "deferred computation" mechanism is useful, but that one limited to the context of function parameters does more harm than good is scoped narrowly to that single use. I keyword version might bridge that gap by introducing "later" or "defer" or "delay" in a narrow context, but not foreclosing its later use more broadly. On Wed, Jun 15, 2022 at 8:38 AM Steven D'Aprano wrote: > On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via Python-ideas > wrote: > > > I used to prefer `:=` but coming back to this topic after a long > > interval I am happy with `=>` and perhaps I even like it more, Chris. > > The PEP status is "Draft". What are the chances of something happening > > any time soon, i.e. the PEP being considered by the Steering Committee? > > There's no Sponsor, so it isn't being considered by the SC. That much is > objectively true. > > Beyond that, the following is all my personal opinion, and should not be > taken as definitive or official in any way. Importantly, I have *not* > read back through the entire thread to refresh my memory. However, I > have re-read the PEP in detail. > > There's no consensus that this feature is worth the added complexity, or > even what the semantics are. The PEP punts on the semantics, saying that > the behaviour may vary across implementations. > > There's no consensus on the syntax, which may not matter, the Steering > Council can make the final decision if necessary. But with at least four > options in the PEP it would be good to narrow it down a bit. No soft > keywords have been considered. > > In my opinion, there are weaknesses in the PEP: > > - lack of any reference to previous discussions; > > - no attempt to gather feedback from other forums; > > - no review of languages that offer choice of early or late binding; > > - little attempt to justify why this is better than the status quo; the > PEP seems to take the position that it is self-evident that Python > needs this feature, rather than being a balanced document setting out > both pros and cons; > > - little or no attempt in the PEP to answer objections; > > - examples are all chosen to show the feature in the best possible > light, rather than to show both the good and bad; (e.g. no examples > show the parameter with annotations) > > - failure to acknowledge that at least one of the suggested syntaxes > is visually ambiguous with existing syntax. > > E.g. this would be legal with the PEP's second choice of spelling: > > def func(spam, eggs:=(x:=spam)): > > Even if the parser can distinguish the two uses of `:=` there, its > awfully cryptic. In and of itself, that's not necessarily a fatal flaw > (e.g. slicing) but the benefits have to outweigh the negatives, and the > PEP should be a balanced discussion of both. > > > > -- > 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/V5K2JFT44A57ZXV2GS3OS6MQW2YKXMQN/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- 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/V2WTEHWFOL5LTW76QVGYMAGSNUAHOR6R/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via Python-ideas wrote: > I used to prefer `:=` but coming back to this topic after a long > interval I am happy with `=>` and perhaps I even like it more, Chris. > The PEP status is "Draft". What are the chances of something happening > any time soon, i.e. the PEP being considered by the Steering Committee? There's no Sponsor, so it isn't being considered by the SC. That much is objectively true. Beyond that, the following is all my personal opinion, and should not be taken as definitive or official in any way. Importantly, I have *not* read back through the entire thread to refresh my memory. However, I have re-read the PEP in detail. There's no consensus that this feature is worth the added complexity, or even what the semantics are. The PEP punts on the semantics, saying that the behaviour may vary across implementations. There's no consensus on the syntax, which may not matter, the Steering Council can make the final decision if necessary. But with at least four options in the PEP it would be good to narrow it down a bit. No soft keywords have been considered. In my opinion, there are weaknesses in the PEP: - lack of any reference to previous discussions; - no attempt to gather feedback from other forums; - no review of languages that offer choice of early or late binding; - little attempt to justify why this is better than the status quo; the PEP seems to take the position that it is self-evident that Python needs this feature, rather than being a balanced document setting out both pros and cons; - little or no attempt in the PEP to answer objections; - examples are all chosen to show the feature in the best possible light, rather than to show both the good and bad; (e.g. no examples show the parameter with annotations) - failure to acknowledge that at least one of the suggested syntaxes is visually ambiguous with existing syntax. E.g. this would be legal with the PEP's second choice of spelling: def func(spam, eggs:=(x:=spam)): Even if the parser can distinguish the two uses of `:=` there, its awfully cryptic. In and of itself, that's not necessarily a fatal flaw (e.g. slicing) but the benefits have to outweigh the negatives, and the PEP should be a balanced discussion of both. -- 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/V5K2JFT44A57ZXV2GS3OS6MQW2YKXMQN/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Mon, Jun 13, 2022 at 07:41:12AM -0400, Todd wrote: > This has been proposed many times. You can check the mailing list history. > Such proposals have been even less popular then PEP 671, since it requires > a new keyword, which is generally avoided at nearly all costs, Now that Python is using a PEG parser, adding a soft keyword is no big deal. We could use a named keyword: def spam(arg = defer default_expression): pass without affecting code that used "defer" as a variable or function name. We could even write: def spam(defer = defer defer()): ... where the same word "defer" refers to a parameter, a soft keyword, and a function call, all in the same function signature. Needless to say one should not make a habit of this. But it would be allowed. -- 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/5V2SEWXFCVDI6RHBVX4QME4ZAYL4NPPO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, Jun 15, 2022 at 10:44:28AM -, Mathew Elman wrote: > Could this be the behaviour of passing in an Ellipsis? e.g. > > def foo(defaults_to_one=1): > return defaults_to_one > > assert foo(...) == foo() It isn't clear to me whether your question is a request for clarification (does the PEP mean this...?) or a request for a change in behaviour (could you change the PEP to do this...?). Why would you want to type `foo(...)` when you could just type `foo()`? > The only place that I am aware of the Ellipsis being used is in index > notation (numpy). > So this would have likely an impact on __getitem__ or the slice object. Ellipsis has been around for over twenty years so we have to assume it would have an impact on thousands of programs. We don't just care about famous, popular libraries like numpy, we care about breaking little scripts used by one person too. -- 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/M23GNYPCZAVCFOURUBCGURL64U6DEWBR/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Wed, 15 Jun 2022 at 20:45, Mathew Elman wrote: > > Could this be the behaviour of passing in an Ellipsis? e.g. > > def foo(defaults_to_one=1): > return defaults_to_one > > assert foo(...) == foo() > > def bar(something=...): > return foo(something) > > assert bar() == foo() > > def baz(arg): # no defaults > return arg > > assert baz(...) == ... > > The only place that I am aware of the Ellipsis being used is in index > notation (numpy). > So this would have likely an impact on __getitem__ or the slice object. > > *Alternatively* a subtype of Ellipses specifically for when used in argument > defaults DefaultEllipsis (or equivalent): > def foo(x=...): > return x > > assert isinstance(foo(), EllipsisType) > assert foo() != Ellipsis > > assert isinstance(foo(...), EllipsisType) > assert foo(...) == Ellipsis No, because Ellipsis is a very real object and could be passed as a parameter at any time. Although, since it's unusual, it's actually a slightly deoptimized case in my reference implementation - or rather, whenever a function observes that it's been passed Ellipsis, it checks to see if the parameter was actually omitted. Fundamentally, Python does not have any value that indicates the lack of a value. And having worked with a number of JavaScript APIs where undefined is used as "absent", I don't want to inflict that on anyone. (For instance, classList.toggle("some-class", X) will add the class if X is truthy, remove it if it's falsy, but... toggle if X is undefined. Which is otherwise falsy. Extremely annoying to try to track down.) The standard way in Python to indicate "no value" is to raise an exception instead of returning, but that doesn't work for parameters. You can use sequence unpacking to achieve that sort of effect, though. foo(*([] if x is ... else [x])) This will skip the parameter if x is Ellipsis. Obviously, you use this only when you know you'll never use Ellipsis as an actual value, though, so this can't be done in the language, but it could be useful. 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/XJUTOQWWWLVHWQFENJXA67GXIEYOOWEJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
Could this be the behaviour of passing in an Ellipsis? e.g. def foo(defaults_to_one=1): return defaults_to_one assert foo(...) == foo() def bar(something=...): return foo(something) assert bar() == foo() def baz(arg): # no defaults return arg assert baz(...) == ... The only place that I am aware of the Ellipsis being used is in index notation (numpy). So this would have likely an impact on __getitem__ or the slice object. *Alternatively* a subtype of Ellipses specifically for when used in argument defaults DefaultEllipsis (or equivalent): def foo(x=...): return x assert isinstance(foo(), EllipsisType) assert foo() != Ellipsis assert isinstance(foo(...), EllipsisType) assert foo(...) == Ellipsis ___ 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/C2L3COISYSSVFAYXRFVVNPFBBOQYXVQU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Tue, 14 Jun 2022 at 21:00, Rob Cliffe via Python-ideas wrote: > > I used to prefer `:=` but coming back to this topic after a long > interval I am happy with `=>` and perhaps I even like it more, Chris. > The PEP status is "Draft". What are the chances of something happening > any time soon, i.e. the PEP being considered by the Steering Committee? > Or is it still too controversial, or is there some other obstacle? > In case it's not clear, I support the PEP. I think it plugs an obvious gap. The main obstacle is that I got weary of responding to emails on it, put it on the back burner, and let the topic go cold. To revive it, what I'd recommend is: Go through the PEP and figure out everything that *you* would need to see done before *you* would approve it, supposing that you were a member of the SC. Then either suggest wording changes, or at least list your concerns, and we can reopen the discussion. 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/KJ6D6A7BANEVEPOT3NPTU7RJD4LW6IYM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
I used to prefer `:=` but coming back to this topic after a long interval I am happy with `=>` and perhaps I even like it more, Chris. The PEP status is "Draft". What are the chances of something happening any time soon, i.e. the PEP being considered by the Steering Committee? Or is it still too controversial, or is there some other obstacle? In case it's not clear, I support the PEP. I think it plugs an obvious gap. Best wishes Rob Cliffe On 13/06/2022 09:38, Steve Jorgensen wrote: To clarify my statement about readability of the '@' prefix option… I think that its meaning is less clear if one doesn't already know what the syntax means. I think the code would be easier to skim, however, using that option after one does know its meaning. My favorite options are '@' or '?=' (tied), followed by ':=' followed by '=>'. ___ 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/TDPKOPGWQ4ORRJDHWJMX5GMW2TQ5FI5B/ 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/KWYUYR3WT3VFUI4CNCGQT6ZZYOIBUPQB/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!
On Sun, Jun 12, 2022, 16:22 Bluenix wrote: > I stumbled upon PEP 671 again today, and for what it's worth I fully agree > with everything said here. > > For the same reasons as you listed, I am generally opposed to PEP 671. > Wrapping functions in one way or another is extremely common and this PEP > will make a problem which is currently super small much bigger - the > inability to have a function's defaults apply without messing with `*args` > and `**kwargs`. > > The reason this probably isn't brought up a lot is because of the > existence of None. A wrapping function can set its default to None matching > the wrapped function's default. If the wrapped function were to use PEP 671 > this would cause the wrapping function to need to go to dynamic `*args` and > `**kwargs` to match this behaviour. > > JavaScript users can use `undefined` for this; if you pass `undefined` to > a parameter in JavaScript, the default will be applied. I think that Python > should have a similar mechanic (but that's another discussion) which would > need to be added before PEP 671. Together that adds up to being years away > (because of dependencies minimum Python requirement, etc) and at that point > I would rather see the current status quo being upheld and PEP 671 deferred. > > Tl;Dr PEP 671 makes things worse without other additions This has been proposed many times. You can check the mailing list history. Such proposals have been even less popular then PEP 671, since it requires a new keyword, which is generally avoided at nearly all costs, and requires it either be restricted to only being used in defs, or will just end up like None where people are passing it as arguments, which defeats the purpose. You may not like PEP-671, but it at least provides a feasible solution. Using a new special parameter is never going to fly. ___ 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/YFONN2M73HZE6CGQL2SYSGBOEK2AJCKQ/ Code of Conduct: http://python.org/psf/codeofconduct/