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/

Reply via email to