On Sun, Oct 24, 2021 at 1:00 PM Steven D'Aprano <st...@pearwood.info> wrote: > > On Sun, Oct 24, 2021 at 06:54:36AM +1100, Chris Angelico wrote: > > [...] > > Teaching moment. Currently, the equivalent second function would be this: > > > > def f2(l=None): > > if l is None: l = [] > > l.append(4) > > return l > > > > And the whole "early bind or late bind" question is there just the > > same; the only difference is that the late binding happens somewhere > > inside the function body, instead of being visible as part of the > > function's header. (In this toy example, it's the very next line, > > which isn't a major problem; but in real-world examples, it's often > > buried deeper in the function, and it's not obvious that passing None > > really is the same as passing the array's length, or using a system > > random number generator, or constructing a new list, or whatever it > > is.) > > I challenge that assertion. I've never knowingly seen a function where > the late binding is "buried deeper in the function", certainly not deep > enough that it is not obvious. It is a very strong convention that such > late binding operations occur early in the function body. > > You know, before you use the parameter, not afterwards *wink* > > But then I mostly look at well-written functions that are usually less > than two, maybe three, dozen lines long, with a managable number of > parameters. > > If you are regularly reading badly-written functions that are four pages > long, with fifty parameters, your experience may differ :-) > > The bisect function you gave earlier is a real-world example of a > non-toy function. You will notice that the body of bisect_right: > > - does the late binding early in the body, immediately after checking > for an error condition; > > - and is a manageable size (19 LOC).
What I'm more often seeing is cases that are less obviously a late-binding, but where the sentinel is replaced with the "real" value at the point where it's used, rather than up the top of the function. > https://github.com/python/cpython/blob/3.10/Lib/bisect.py > > The bisect module is also good evidence that this proposal may not be as > useful as we hope. We have: > > def insort_right(a, x, lo=0, hi=None, *, key=None): > > which just passes the None on to bisect_right. So if we introduced > optional late-binding, the bisect module has two choices: > > - keep the status quo (don't use the new functionality); > > - or violate DRY (Don't Repeat Yourself) by having both functions > duplicate the same late-binding. > > It's only a minor DRY violation, but still, if the bisect module was > mine, I wouldn't use the new late-binding proposal. > > So I think that your case is undermined a little by your own example. > The truth is, though, that the default for hi is not None - it's really "length of the given list". Python allows us to have real defaults for parameters, rather than simply leaving trailing parameters undefined as JavaScript does; this means that you can read off the function header and see what the meaning of parameter omission is. Late-binding semantics allow this to apply even if the default isn't a constant. If this proposal is accepted, I would adopt the DRY violation, since it would literally look like this: def insort_right(a, x, lo=0, hi=>len(a), *, key=None): def bisect_right(a, x, lo=0, hi=>len(a), *, key=None): def insort_left(a, x, lo=0, hi=>len(a), *, key=None): def bisect_left(a, x, lo=0, hi=>len(a), *, key=None): That's not really a lot of repetition, and now everyone can see that the default lo is 0 and the default hi is the length of a. Four "hi=>len(a)" isn't really different from four "hi=None" when it comes down to 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/BLL643IZYZLYAUVX6CGDIJFFCNMEE4QO/ Code of Conduct: http://python.org/psf/codeofconduct/