C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [Proposal] Identifiers For Pattern Matching

From: Михаил Найденов <mihailnajdenov_at_[hidden]>
Date: Mon, 17 Apr 2023 18:51:43 +0300
Hello, updated the proposal, adding a chapter on why having type and
expression selections under one syntax is undesirable, a paragraph on
similarities b/w captures and bindings, a note about "last pattern" as well
as minor tweaks and example fixes.

On Thu, Mar 16, 2023 at 8:25 PM Barry Revzin <barry.revzin_at_[hidden]> wrote:

>
>
> On Thu, Mar 16, 2023 at 11:20 AM Михаил Найденов <mihailnajdenov_at_[hidden]>
> wrote:
>
>>
>>
>> On Thu, Mar 16, 2023 at 2:53 AM Barry Revzin <barry.revzin_at_[hidden]>
>> wrote:
>>
>>>
>>>
>>> On Wed, Mar 15, 2023 at 11:30 AM Михаил Найденов <
>>> mihailnajdenov_at_[hidden]> wrote:
>>>
>>>>
>>>>
>>>> On Mon, Mar 13, 2023 at 12:24 AM Barry Revzin <barry.revzin_at_[hidden]>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Sun, Mar 12, 2023 at 4:48 AM Михаил Найденов via Std-Proposals <
>>>>> std-proposals_at_[hidden]> wrote:
>>>>>
>>>>>> Hello, attached is a proposal on the topic of identifiers inside
>>>>>> pattern matching.
>>>>>> It is a section of an old proposal I wrote few months back, which did
>>>>>> not account for the existence of p2688, as well as p2211, which renders
>>>>>> many sections of it no longer needed.
>>>>>>
>>>>>>
>>>>> At a high level, it's difficult to tell what the paper is actually
>>>>> proposing - since first it says talks about naturally introducing
>>>>> relational patterns, then it says it's not proposing them. Then it says
>>>>> it's proposing "== *expression*" as the expression pattern, but then
>>>>> frequently throughout the paper == isn't used, but then you say it's
>>>>> optional if it's the "last pattern" - But what does last pattern mean? When
>>>>> is == mandatory and when it is optional?
>>>>>
>>>>
>>>> Not having == is optional if the identifier is the last pattern to be
>>>> matched. Not sure how better to describe it, but will give another look.
>>>>
>>>>
>>>>>
>>>>> I also can't tell what actual grammar you're proposing, and it doesn't
>>>>> help that throughout the paper you're frequently using the same identifier
>>>>> to mean both a type and a variable name, which makes it hard to tell what
>>>>> the patterns even mean. I'm not sure why that case is interesting to begin
>>>>> with, much less needs to be so prevalent. There's no ambiguity to the
>>>>> compiler in the Alternative Pattern for <x>, it might be ambiguous to the
>>>>> reader, but not to the compiler. In the same way that template <T V> could
>>>>> be a constrained type (if T names a concept), or a non-type template
>>>>> parameter (if T names a type), or a deduced non-type template parameter (if
>>>>> T is a template-id).
>>>>>
>>>>
>>>> This is not the same. When the user creates a template, he/she creates
>>>> a definition.
>>>> When the user creates PM - he/she creates an expression, expecting
>>>> something to happen.
>>>>
>>>> Say the user writes <size> => ... and there is type `size`. What
>>>> happens when there is constexpr auto size = 1 also in scope? I
>>>> *genuinely *don't know what happens.
>>>>
>>>> If I want the type, what should I write? If I want the constant, what
>>>> should I write? Can I have both?
>>>> It makes sense to be able to match both on index and on type for the
>>>> same inspected, right?
>>>>
>>> It'd be the same rule we have for this in every other context: if you
>>> have a type and a value of the same name in a context where either is
>>> possible, lookup finds the variable. If you want the type you have to use
>>> an elaborated type. As in:
>>>
>>> template <typename T> constexpr int f() { return 0; }
>>> template <auto V> constexpr int f() { return 1; }
>>>
>>> struct size { };
>>> size size;
>>>
>>> static_assert(f<struct size>() == 0);
>>> static_assert(f<size>() == 1);\
>>>
>>
>> Ok, this means, a PM* will change definition, and as a result possibly
>> meaning*, *if someone adds a `size` variable in any scope above it.
>> How is that not bad?
>>
>
> That's... the way lots of stuff in the language already works in a lot of
> contexts. Is this really a problem? How is this something pattern matching
> specifically needs to solve? Generally speaking, people just avoid this
> problem entirely with naming conventions - whether by having type names in
> different case or simply using different words to name them.
>
>
>>
>>
>> *PM, written for a type `size` initially, naturally w/o struct of course,
>> this is not C.
>>
>>
>>>
>>>
>>>>
>>>>
>>>>>
>>>>> I'm assuming that the proposal is:
>>>>>
>>>>>
>>>>> - the alternate pattern is *type-id pattern*
>>>>> - the expression pattern is == *expression *(except sometimes not?
>>>>> I don't understand when you would need the ==)
>>>>> - the identifier pattern is either *identifier=* or &*identifier*=
>>>>>
>>>>> P2688 has a lot of examples that are both short and complete. I would
>>>>> encourage you to simply use those.
>>>>>
>>>>> ----
>>>>>
>>>>
>>>>
>>>>>
>>>>> But ultimately we're *just *talking about a change in syntax? What's
>>>>> wrong with the syntax proposed in P2688? I don't really see much of an
>>>>> argument there, except that you don't like the <>s used by the alternative
>>>>> pattern in P1371/P2688?
>>>>>
>>>>
>>>> The syntax with let is heavily compromised by the fact, it is an
>>>> one-off. I also don't see how immutable bindings could be introduced
>>>> unless we go for yet another one off, so it is not just about the syntax,
>>>> it is about features too. Granted, binding to existing variable will be
>>>> more or less natural, I admit.
>>>>
>>>
>>
>>> This would also be a one-off? Also, do other languages even support
>>> immutable bindings? I'd imagine if we really wanted such a thing, the
>>> existing proposal has a fairly natural extension - it could be spelled "let
>>> const *identifier*".
>>>
>>
>> So, on one side we have immutable by default, one extra character for
>> mutability (in a context where character count matters a lot) and on the
>> other we have mutability by default and 5+1 more characters for
>> immutability.
>> And somehow, the second is better, or good enough, and no effort should
>> be made to investigate an alternative?
>>
>
> Well, it's really up to you to argue that effort should be made to
> investigate. Why should bindings be immutable by default? And why is & a
> good character to indicate mutability?
>
>
>>
>>
>>>
>>>
>>>> The issue with <> is also about expression vs type selection as noted.
>>>>
>>>
>>> Not an issue, as noted.
>>>
>>>
>>>>
>>>>
>>>>>
>>>>> Concretely, I don't think the syntax n= syntax for bindings is
>>>>> particularly good. Your model is init-capture in lambdas, but init-capture
>>>>> is lambdas isn't at all the same thing as bindings in a pattern, so I'm not
>>>>> sure that it's a good model.
>>>>>
>>>>
>>>> Ok, but it is the only model that does not invent a new mini language
>>>> *and *is quite feature rich as a side effect of an existing syntax. It
>>>> must be considered out of clear conscience.
>>>>
>>>
>>
>>> It is just as much a new mini language, just with different syntax.
>>>
>>
>> PM is by definition a new mini language, but in one case we reuse the
>> existing syntax with no change in meaning (though details will have to
>> change),
>> in the other we lift constructs from other languages, introducing a real
>> new mini language, completely inconsistent with the rest.
>>
>
> By "no change in meaning (though details will have to change)", what you
> mean is that there is of course a change in meaning.
>
> To repeat myself, "n=" in a lambda-introducer is not a binding, it is
> declaring a new, independent variable. So using "n=" to mean a binding is
> not reusing syntax with no change in meaning. Also, if "Point p" is a valid
> pattern in your model (assuming that you don't need to write "Point ==p"),
> then that very much does not mean declaring a variable named p of type
> Point - it's matching a Point whose value compares equal to p. That's not
> the same meaning at all.
>
>
>>
>>
>>>
>>>
>>>>
>>>>
>>>>> Having a distinct syntax for mutable vs immutable bindings is
>>>>> interesting, but I'm not sure & is a good syntax to indicate mutability.
>>>>> And if you always have a marker for the identifier pattern, we're just
>>>>> talking about the difference between "let x" and "x=", so I don't think
>>>>> you'd need the "==" for the expression pattern ever. The issue largely
>>>>> becomes a question of disambiguating types.
>>>>>
>>>>
>>>> Types are most important to stay without a marker, mainly because there
>>>> is no such marker in the language (so far), but also because it is expected
>>>> to be able to "just" name the type inside PM, like any other such system,
>>>> in any other language.
>>>> The second point gains additional weight, considering the PM's primary
>>>> goal is type matching! It must be first class.
>>>> So yes the == is exactly for disambiguating types vs. values.
>>>>
>>>
>>
>>> Sure, in other languages, if I wanted to match a Point I would just
>>> write Point(x, y) or Point{x, y} or Point(x=x, y=y), etc. - which matches
>>> their syntax on the construction side, whereas the P1371/P2688 syntax is
>>> <Point> let [x, y]. But the syntax you're proposing isn't even the
>>> construction syntax anyway? It's Point [&x=, &y=], which is still a bespoke
>>> syntax for this case, and it's not any more first class than the existing
>>> proposal's syntax - it's just a slightly different syntax.
>>>
>>
>> Matching on type is first class, all else you wrote is not type matching,
>> but deconstruction and binding.
>>
>
> I don't know what you mean by this. <Point> is also first class matching
> on type, it's just a different syntax than what you're proposing. It's not
> any less "first class".
>

<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Няма
вирусиwww.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

Received on 2023-04-17 15:51:58