There was a typo in my post and I want to avoid getting into a pedantic 
tangent about how to properly indent multi-line function signatures, so 
hopefully this will "nip it in the bud", so to speak. 

When I wrote:

def my_func(
            param: Annotation[stuff],
            other_param: MoreAnnotation[things],
            another_param: SomeType = default_value,
            yet_another_param: EvenMoreAnnotation = another_default) -> 
ReturnType:
    # code goes here ...

I meant the parameter list to be at two indentation levels so it's visually 
distinguishable from the function body at one indentation level. I 
accidentally put the parameter list at three indentation levels which 
happen to align with the open parentheses after `def my_func` which is not 
what I wanted to suggest as good practice because then functions with long 
names would have their parameter list indented way far over and it would 
hurt readability. The following is closer to what I intended: 






*def my_func(        param: Annotation[stuff],        other_param: 
MoreAnnotation[things],        another_param: SomeType = default_value,    
    yet_another_param: EvenMoreAnnotation = another_default) -> 
ReturnType:    # code goes here ...*

On Thursday, December 2, 2021 at 5:56:36 PM UTC-6 abed...@gmail.com wrote:

> If the coder's intent is to have an optional parameter default to an empty 
>> list, the most EXPLICIT way to encode that intent would be to have the 
>> optional parameter default to an empty list. It's categorically LESS 
>> EXPLICIT to bind the parameter to None and add boilerplate code to the body 
>> of the function to correct that.
>
>
> I think it's a nearly philosophical distinction but right now there is no 
> such thing as “an optional parameter defaulting to an empty list”. Or 
> rather there is, but it's not what you really want “a different empty list 
> for every call of the function”.
>
>
> It's not philosophical. It's pretty cut and dry: If you want a parameter 
> to default to an empty list, it's objectively more explicit to make the 
> parameter default to an empty list than to make it default to a sentinel 
> value and assign it to an empty list later. Of course that capability 
> doesn't exist yet, that's what this whole discussion is about.
>
> To me, it's not absurd that “creating a new object and binding the 
>> parameter to it” is sufficiently complex that we don't cram it into the 
>> function signature. It's fine to just have code in the function body... 
>
>
> It may not be absurd to you, but to me, the function signature is the 
> correct place to put all things related to the function signature, the 
> function body is for business logic. You're argument about "cramming things 
> in the function signature" is more about practical constraints like keeping 
> things on one line which is less important to me than putting things where 
> they belong. You can always expand the signature, which is a practice I 
> wish more people did.
>
> Instead of this:
>
> def my_func(param: Annotation[stuff], other_param: MoreAnnotation[things], 
> another_param: SomeType = default_value, yet_another_param: 
> EvenMoreAnnotation = another_default) -> ReturnType: 
>      # code goes here ...
>
> just do this:
>
> def my_func(
>             param: Annotation[stuff],
>             other_param: MoreAnnotation[things],
>             another_param: SomeType = default_value,
>             yet_another_param: EvenMoreAnnotation = another_default) -> 
> ReturnType:
>     # code goes here ...
>
> The repulsion against "cram[ing] [defaults] into the function signature" 
> is more a problem with long function signatures than anything else. You can 
> always use the usual suspects to make it more readable:
>
> instead of this:
>
> def my_func(param: SomeType => long and complicated logic that's hard to 
> read and fits too much in one line) -> ReturnValue: 
>     ... 
>
> just do this: 
>
> def _provide_default() -> SomeType: 
>     the same logic as above 
>     but more readable
>     and better organized
>
> def my_func(param: SomeType => _provide_default()) -> ReturnValue:
>     ...
>
> especially since there does not seem to be an overwhelming consensus for 
>> either the concept or the proposed syntaxes.
>
>
> The above explanation of why it's objectively more explicit is not subject 
> to the consensus of the python ideas list. It's a refutation of the 
> argument that current familiar work-arounds are somehow more explicit. That 
> somehow binding to a sentinel is actually an explicit way of "telling the 
> function you want it to provide a default value" rather than a work-around 
> that's so familiar that you no longer even question if it's all that 
> explicit in the first place.
>
> (Also maybe not calling what we have been happily (at least for some of 
>> us) doing for years "a hack" would be a good way to have a more civil 
>> discussion)
>
>
> Why? It's not a personal attack. The whole point is to prod people into 
> rethinking what they've become inured to.
>
> On Thu, Dec 2, 2021 at 3:11 PM Evpok Padding <evpok....@gmail.com> wrote:
>
>> On Thu, 2 Dec 2021, 21:48 abed...@gmail.com, <abed...@gmail.com> wrote:
>>
>>> Nicholas Cole
>>> "There is nothing that this proposal makes possible that is not already
>>> possible with more explicit code."
>>>
>>> There's nothing any of Python's syntax makes possible that is not 
>>> already possible with Brainfuck or any other language that's Turing 
>>> complete. The current hacks used to get around the lack of late-bound 
>>> optional parameters aren't more explicit. They just require more code. If 
>>> the coder's intent is to have an optional parameter default to an empty 
>>> list, the most EXPLICIT way to encode that intent would be to have the 
>>> optional parameter default to an empty list. It's categorically LESS 
>>> EXPLICIT to bind the parameter to None and add boilerplate code to the body 
>>> of the function to correct that.
>>
>>
>> I think it's a nearly philosophical distinction but right now there is no 
>> such thing as “an optional parameter defaulting to an empty list”. Or 
>> rather there is, but it's not what you really want “a different empty list 
>> for every call of the function”. To me, it's not absurd that “creating a 
>> new object and binding the parameter to it” is sufficiently complex that we 
>> don't cram it into the function signature. It's fine to just have code in 
>> the function body, especially since there does not seem to be an 
>> overwhelming consensus for either the concept or the proposed syntaxes.
>>
>> (Also maybe not calling what we have been happily (at least for some of 
>> us) doing for years "a hack" would be a good way to have a more civil 
>> discussion)
>>
>> Best
>>
>> E
>>
>
_______________________________________________
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/O5GDCBMNUEPTSYS2AVZOFY4IUZAWMXFH/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to