C++ Logo

std-proposals

Advanced search

Re: Proposal: template function solution to Pythonic optional function arguments

From: Richard Hodges <hodges.r_at_[hidden]>
Date: Mon, 20 Jul 2020 22:35:30 +0200
On Mon, 20 Jul 2020 at 21:11, Arthur O'Dwyer via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Mon, Jul 20, 2020 at 12:43 PM Richard Hodges via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Mon, 20 Jul 2020 at 18:03, codusnocturnus via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> This would be great - just remove the braces, and the .’s, and the
>>> struct.
>>>
>>
>> At this point it becomes an argument over syntax [...]
>>
>> I think it's common to think, "language X has a nice way of expressing Y
>> - why don't we do that too?"
>> I can be guilty of that just like anyone else.
>> But in the end, if a language gives you a way to *express intent*, one
>> might wonder whether it's worth expending effort in making syntax nicer for
>> niche use cases in favour of providing more utility or fixing design bugs.
>>
>
> Richard, apparently your notion of "express intent" doesn't match up with
> mine.
>

It seems to me that I have miscommunicated.

I think my position is that the language already provides the ability
to *express
intent* through overloads (and indeed types).

Although we have the ability to pass arguments through structs with
defaulted optionals in order to simulate python's easy flexibility,
allowing people to do this easily might be more of a vanity project than
fulfilling an actual use case for which a statically typed language has
been selected.

When people ask me why I choose C++ for commercial projects, the answer is
invariably "determinism". Python's flexibility is wonderful for a number of
RAD applications, but if I want rock solid stability with no GC pauses I'll
choose C++ and live with the fact that I may have to write two overloads to
a function.

Just to be clear: the struct approach is simply meant to demonstrate that
the language already has the ability to communicate optional named
parameters (actually in more than one way). It was in no way intended to be
a proposal for future language development.


> When I say that C++ *gives the programmer a way to express his intent*,
> what I mean is that C++ provides a specific syntax for that exact intent,
> which is intended to be used if and only if that's the programmer's intent.
> For example, when I see
>
> void foo(const std::string& x);
>
> I know that the programmer's *intent* is that `x` should remain unchanged
> by a call to `foo`. Now, physically, `foo` could still change `x`, because
> of `const_cast`; but in practice the `const` keyword gives me a hint that
> in general is really strongly correlated with the programmer's *intent*.
>
> Similarly, if I see an overload set consisting of the signatures
>
> void foo(int x, int y);
> void foo(int x, int y, bool dx, bool dy);
>
> that's a very strong indication that the programmer *intends* to permit
> the caller to call `foo` with either of these signatures, and no others. I
> consider overloading a good example of "features that allow us to express
> intent."
>
> On the other hand, if I see
>
> void foo(int x, int y, bool dx=false, bool dy=false);
>
> that's much less of a hint about intent, because it indicates that
> *either* the programmer meant to permit a call like `foo(1, 2, true)` or
> *else* the programmer doesn't know what they're doing. (In my experience,
> it's usually the latter.)
>
> To your specific example: If I see
>
> struct FooParams { int x, y; bool dx=false, dy=false; };
> void foo(FooParams params);
>
> well, that's basically no hint at all as to what the programmer intends.
> Sure, it physically *permits* me to call `foo({1, 2, .dx=true})` or
> `foo({})` or `foo(FooParams(1, 2, false, true))` — but the code gives me
> practically *zero* indication of what the programmer *intended* me to do!
>
> To me, "a feature that allows me to express intent" would be the exact
> *opposite* of "a stack of features that can be house-of-cardsed into
> something that physically resembles what I'm trying to do."
>
> Also from C++20: The `concept` keyword doesn't add anything physically
> helpful(*) over and above the preexisting house-of-cards that was `inline
> constexpr bool fooable_v`; but it does permit programmers to express their
> intent better. (* — It adds subsumption, but I don't consider that to be
> helpful.)
> Constraining a function template with a `requires` clause doesn't add
> anything physically helpful(*) over and above the preexisting
> `enable_if`/return-type-SFINAE tricks; but it does permit programmers to *express
> their intent* better. (* — It raises the template's overload-resolution
> priority, but I don't consider that to be helpful.)
> Even C++20's `auto operator<=>(const Me&) = default;` could be considered
> to "express intent" better than what came before it.
>
> I'm sympathetic to the idea that programming languages should permit the
> programmer to express intent.
> I don't think this specific thread has suggested any specific ideas that
> would meet that bar w.r.t. named parameters, though. Named parameters are a
> very old idea that a *lot* of people have tried and failed to shoehorn
> into C++.
>
> –Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>


-- 
Richard Hodges
hodges.r_at_[hidden]
office: +442032898513
home: +376841522
mobile: +376380212

Received on 2020-07-20 15:38:59