>
> >>      function(*, dunder, invert, private, meta, ignorecase)
> >>
> >
> >
> > No reader will ever have to think about the difference. They will simply
> > see the second version and know which arguments are being passed.
>
> I seem to be immune to this magical knowledge.
>

Sorry, what? How is there any doubt that the arguments being passed are
dunder, invert, private, meta, and ignorecase? They're right there.

Now, which parameters those arguments are bound to is less obvious, but:


   1. When you read the function call, you're thinking about the arguments,
   not the parameters. You can see which information goes into the function,
   and the first question you should ask yourself is 'is that the right
   information?'.
   2. Even if you have no idea what the parameters of the function are, you
   can already reasonably guess that they match the argument names, and that
   guess is correct! If you have some idea what the parameter names are, you
   can be more confident in that guess. Or, if you didn't know the parameter
   names, but you know what the `**` separator means, now you know the names.
   3. You probably only start to think about parameter binding when you
   open up the function definition, and when you do that, binding is still
   probably not the first thing you look at. You're probably thinking about
   what the function does in the body.
   4. If there are just a few arguments, you're less likely to miss or
   ignore the `**`.
   5. If there are many arguments, you're less likely to notice any
   mismatch between argument and parameter positions that might falsely make
   you think something is wrong. That is, you're less likely to either
   remember the parameter order or to go through the trouble of inspecting and
   comparing the orders.
   6. If you're thinking about parameter binding and argument order, you're
   inspecting the arguments at least somewhat closely, and will almost
   certainly notice that the `**` is present. If you know what it means,
   problem solved. If you don't, you're at least likely to think about it and
   try looking it up or ask someone. It takes a very specific kind of
   skepticism/suspicion to think "the previous programmer messed up the
   argument order so these parameters are definitely bound wrong, and also
   that weird `**` that I don't know the meaning of has no bearing on that,
   and I'm not going to check with a print() or a debugger".

In summary, I think that the vast majority of the time, the new syntax will
cause no confusion (even when it potentially could have) because people
will skim and follow their intuition. Occasionally, it might cause brief,
mild confusion, and that will mostly only be one or two times for each
programmer as they learn the new syntax. I can't see it causing serious
confusion outside of very specific and rare circumstances.

> Also, your examples are clearly demonstrating that using the shortcut
> makes
> > it easier to avoid mistakes.
>
> It shows that using positional parameters makes it easier to make
> mistakes, but that's not news.
>

Right, but people use them anyway, sometimes even to solve the exact
problem we're talking about. You're responding to me responding to Steven
D'Aprano, here's what he said just slightly earlier:

We're not talking about positional arguments here. If you want to
> include positional arguments in the analysis, then we already have a
> perfectly good way to write function calls without repeating outselves:
>     # Instead of this:
>     function(spam=spam, eggs=eggs, cheese=cheese)
>     # Just do this:
>     function(spam, eggs, cheese)
> And we're done, the problem is solved, and no new syntax is needed.


That's bad, and we should discourage that. Encouraging people to safely
pass named arguments instead of abusing positional arguments would improve
the readability and correctness of code overall.

Below are some cases from the CPython repo of people passing many
positional arguments. They could be improved by using keyword arguments
more, but with the currently available syntax, that would be very verbose
and undesirable, so it's understandable that it wasn't written that way in
the first place and hasn't been changed since then.

```
File "Lib/subprocess.py", line 947
            self._execute_child(args, executable, preexec_fn, close_fds,
                                pass_fds, cwd, env,
                                startupinfo, creationflags, shell,
                                p2cread, p2cwrite,
                                c2pread, c2pwrite,
                                errread, errwrite,
                                restore_signals,
                                gid, gids, uid, umask,
                                start_new_session)

File "Lib/subprocess.py", line 1752
                    self.pid = _posixsubprocess.fork_exec(
                            args, executable_list,
                            close_fds, tuple(sorted(map(int, fds_to_keep))),
                            cwd, env_list,
                            p2cread, p2cwrite, c2pread, c2pwrite,
                            errread, errwrite,
                            errpipe_read, errpipe_write,
                            restore_signals, start_new_session,
                            gid, gids, uid, umask,
                            preexec_fn)

File "Lib/distutils/ccompiler.py", line 692
        self.link(CCompiler.SHARED_LIBRARY, objects,
                  self.library_filename(output_libname, lib_type='shared'),
                  output_dir,
                  libraries, library_dirs, runtime_library_dirs,
                  export_symbols, debug,
                  extra_preargs, extra_postargs, build_temp, target_lang)

File "Lib/distutils/ccompiler.py", line 713
        self.link(CCompiler.SHARED_OBJECT, objects,
                  output_filename, output_dir,
                  libraries, library_dirs, runtime_library_dirs,
                  export_symbols, debug,
                  extra_preargs, extra_postargs, build_temp, target_lang)

File "Lib/distutils/ccompiler.py", line 731
        self.link(CCompiler.EXECUTABLE, objects,
                  self.executable_filename(output_progname), output_dir,
                  libraries, library_dirs, runtime_library_dirs, None,
                  debug, extra_preargs, extra_postargs, None, target_lang)

File "Lib/distutils/cygwinccompiler.py", line 243
        UnixCCompiler.link(self, target_desc, objects, output_filename,
                           output_dir, libraries, library_dirs,
                           runtime_library_dirs,
                           None, # export_symbols, we do this in our
def-file
                           debug, extra_preargs, extra_postargs, build_temp,
                           target_lang)

File "Lib/http/cookiejar.py", line 1563
        return Cookie(version,
                      name, value,
                      port, port_specified,
                      domain, domain_specified, domain_initial_dot,
                      path, path_specified,
                      secure,
                      expires,
                      discard,
                      comment,
                      comment_url,
                      rest)

File "Lib/http/cookiejar.py", line 2057
                c = Cookie(0, name, value,
                           None, False,
                           domain, domain_specified, initial_dot,
                           path, False,
                           secure,
                           expires,
                           discard,
                           None,
                           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/6MSUASDG2WGPBDPHEPL6S5CMUWT5BJWU/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to