On Sun, Oct 24, 2021 at 07:40:26PM -0400, Jon Kiparsky wrote:
I would prefer to build on the fact that arguments already come in two flavors with somewhat different behaviors,
Three. - Positional only. - Positional-or-keyword. - Keyword only. plus two somewhat special `*args` and `**kwargs` parameters that collect whatever is remaining.
and that the ordering of these is determined. Going by this analogy, it would make sense to have late-binding arguments following keyword arguments, set off by some separator, such as a double-pipe:
I want two functions, spam and eggs. Both of them take two positional- or-keyword parameters, "first" and "second", which the caller gives in that order: spam(first, second) eggs(first, second) (Or by keyword, but in the usual case they are given as positional arguments.) In the spam function, first takes a default value using early binding, and second takes a default value using late binding. In the spam function, the defaults are the other way around. Here is how we might declare the function signatures: def spam(first=default, @second=default) def eggs(@first=default, second=default) How would we declare the functions using your proposed syntax? Remember that the calling order is not up for negotiation: it is "first" first and "second" second. I get: def spam(first=default || second=default) def eggs(second=default || first=default) How does the interpreter map those signatures to the calling order? (Please don't say "alphabetical order" *wink*)
We can also easily scan a function definition and know that there is some specialized behavior going on, which is harder to see with a spelling like
def my_func(positional_arg, some_kwarg<="foo", another_kwarg=[]): # body of func
Aside from the symbol being a less-than-or-equal operator, that is a good argument against modifying the equals sign. It disappears into the middle of something which is likely to be quite busy: some_arg:Type=expression where both the Type and the expression are likely to be moderately complex chunks of text. (By the way, there is absolutely no good reason to make a string constant like "foo" a late-bound default. Of course we should allow it syntactically, a string literal is an expression, but linters and code-checkers should flag it.) If we want to make it obvious which parameters use late binding, and we should, then we should tag the parameter with a prefix, as in my examples above. -- Steve