dotnet / dotnet/vblang

Pattern Matching

Open
#124 25 comments 9 reactions 1 assignee Claimed by @AnthonyDGreen View on GitHub
Proposal Prototype-Needed Speclet-Needed
Dominant language
No language data
Stars
328
Forks
71
PR merge metrics
No merged PRs in 30d

Description

Some people have suggested to me that pattern matching doesn't _feel like a VB feature_. What they mean is _"Pattern matching sounds like some advanced programming stuff"_. I disagree. I think pattern matching is very much so a VB feature. In fact, I suggest that most VB programmers, myself included, have spent most of their careers looking at data--be it DB records, or string input, or messages from one device or another--and testing the shape of that data against known patterns, separating structure from content, and extracting select content to fit our needs. That's what every use of the Like operator, the InStr function, and most `If`' and `Select` statements are really doing. They're just going about it in a rather tedious (imperative) way. Pattern Matching is a powerful feature we can add to VB to make the same kinds of tasks we've always been doing much more concise, readable, and declarative.

I propose we extend existing `Case` statements to support a new kind of clause, the `Match` or `Matches` clause (depending on your grammatical proclivities) of the form:

`Case Match` _pattern_ [`When` _expression_]

Where _pattern_ is one of:

**The wildcard pattern**
`*`
Matches all values, including null.

**The variable pattern**
_identifier_ [`?`] [`As` _typename_]

* Declares a new variable with name _identifier_.
* If no type is specified will match any non-null value.
* If a type is specified the value much be of that type.
* If the `?` modifier is used will match null values _but_ will still fail if the value is a non-null value of another type than specified.
* Type of the variable is either the specified type is provided, or inferred from the value being matched if no type is provided, or nullable version in either case if the `?` modifier is used.

**The function pattern**
_expression_ `(` [ _pattern1_ [`,` _pattern2_, ...] ] `)`

* Matches if the function resolved from evaluating _expression_ returns true. This function may optionally provided one or more outputs, each of which is recursively matched against the corresponding specified pattern.

Example:
``` VB.NET
Select Case "1"
Case Integer.TryParse(value) When value > 0
End Select
```

Order of execution in the above example is as follows:
- `Integer.TryParse` is called passing the value of the `Select Case` statement in as its first argument, a new variable named 'value' of the type of the second argument of the `TryParse` method is passed in as the second argument (which is ByRef).
- If the invocation of `TryParse` returns true, execution passes to the `When` clause. The expression `value > 0` is evaluated as true.
- Execution then proceeds into the `Case` block.

**The tuple pattern**
`(` _pattern1_ [`,` _pattern2_, ...] `)`

* Matches a tuple of an arity equal to the number of patterns specified. Recursively matches each element of the tuple against the corresponding pattern.

However, the list doesn't end here. In fact, it's my belief that the tuple pattern is just the first example of a new trend in the language that with each new expression we add for constructing an object, there is a corresponding pattern for decomposing that object that mirrors the construction syntax. For example, one can imagine (and I have) patterns based on decomposing arrays based on the array literal syntax, decomposing strings based on the string interpolation syntax, and decomposing XML fragments based on the XML literal syntax. The JSON literal proposal (#101) also demonstrates this.

The entire `Match` (or `Matches`) clause succeeds if the specified _pattern_ succeeds AND the _expression_ provided in the `When` clause (if provided) evaluates as true. The _expression_ may refer to variables introduced in _pattern_.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.