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@gmail.com> wrote:


On Thu, Mar 16, 2023 at 11:20 AM Михаил Найденов <mihailnajdenov@gmail.com> wrote:


On Thu, Mar 16, 2023 at 2:53 AM Barry Revzin <barry.revzin@gmail.com> wrote:


On Wed, Mar 15, 2023 at 11:30 AM Михаил Найденов <mihailnajdenov@gmail.com> wrote:


On Mon, Mar 13, 2023 at 12:24 AM Barry Revzin <barry.revzin@gmail.com> wrote:


On Sun, Mar 12, 2023 at 4:48 AM Михаил Найденов via Std-Proposals <std-proposals@lists.isocpp.org> 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 meaningif 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". 

Няма вирусиwww.avast.com