Nope,
I don't think this is an undue cognitive burden. If anything I think
the symmetry between the proposed '=>' syntax and the arrow syntax
for lambdas in other languages (potentially even in python in the
future) reduces the cognitive burden significantly, given the there is
an equivalent symmetry with their semantics (in both cases the code is
being evaluated later when something is called).
Steven
gave the following example of a function signature that would be
difficult to visually parse if this proposal and arrow lambdas were
accepted:
def process(func:List->int=>xs=>expression)->int:
And
while I agree that it does sort of stop you in your tracks when you see
this, I think there are a couple of reasons why this is not as big of a
problem as it appears.
Firstly,
I think if you're writing this sort of code, you can improve the
legibility a lot by using appropriate spacing and adding parentheses
around the lambda arguments (even if they're unnecessary for a lambda
with only a single argument, like in Steven's example):
def process(func: (List) -> int => (xs) => expression) -> int:
Personally I find this much easier to visually parse since I'm used to seeing lambdas in the form:
(*args) => expr
So
my brain just kind of groups
`(List) -> int` and `(xs) => expression` into atomic chunks fairly
effortlessly. And this is before even mentioning the *massive*
cognitive assistance provided by syntax highlighting :)
But
at this point I would also like to point out that code like this is
probably going to be vanishingly rare in the wild. The majority of
use-cases for late-bound defaults as far as I can tell are going to be
for mutable defaults (and maybe some references to early-bound
arguments). I don't like the idea of compromising on what is a very
clean and intuitive syntax in 99% of cases to cater to the hypothetical
1% of cases where it admittedly takes a bit more cognitive effort to
parse.
I
agree with the statement Chris made above where he mentioned that the
same symbols sometimes have different meanings based on context, and
that's okay. For example:
def some_func(some_arg: int) -> int: ...
def another_func(another_arg: int = some_func(some_arg=3)) -> int: ...
In
the second function definition above you've got the '=' symbol pulling
double-duty both as declaring an argument for a function def and as a
keyword arg for a function call in the same statement. I think this is
perfectly fine, and I think the same thing is true of the => symbol
being used for both lambdas and late-bound arguments, especially given
they are semantically
related.
3) If "yes" to question 1, would you use it for any/all of (a) mutable
defaults, (b) referencing things that might have changed, (c)
referencing other arguments, (d) something else?
(a)
is the primary use-case I can see myself using this feature for. I'm
not sure what you mean by (b). I can also definitely see some situations
where (c) would be dead useful, though I don't think this would come up
in the sort of code I write as much as (a). Still, when the use-case
for (c) did present itself, I would be *extremely* grateful to have
late-bound defaults to reach for.