Deconstruction, member, and union patterns
These patterns let a match check a record, a deconstructable .NET type, or a union case and take out the values it needs. This avoids separate type checks, casts, and property accesses.
RecordType(pattern1, pattern2, …)— nominal deconstruction pattern. Matches when the scrutinee can be treated asRecordTypeand each positional subpattern matches the corresponding value produced byRecordType’sDeconstructshape.- Record patterns are valid for deconstructable nominal types, including
recordtypes and other nominal types that expose an accessibleDeconstructmethod. - Primary-constructor classes and structs with promoted public
val/varparameters synthesize aDeconstructmethod in declaration order, so the same pattern form works for them. - Each positional element is a pattern, so bindings still require
let/varunless an outer construct such asif let pattern = exprorwhile let pattern = exprsupplies the binding mode. - An element may optionally include a name before the colon
(
Name: pattern). Named elements bind byDeconstructparameter name rather than source position and may appear in any order. Unnamed elements continue to fill the remaining unmatched parameters in declaration order. - A trailing whole-pattern designation may capture the successfully matched
nominal value:
Person(1, name, _) person. - The number of positional elements must match the selected
Deconstructparameters; mismatches are errors. - If a named element does not match any supported deconstruction member/parameter on the target type, the pattern is invalid and reports the member-not-found diagnostic.
- When the scrutinee is a discriminated union,
CaseName(...)in nominal-deconstruction-pattern syntax is interpreted as a discriminated-union case pattern and binds the case payload positionally.
- Record patterns are valid for deconstructable nominal types, including
Member patterns
.Case/Type.Case— member pattern. Matches a named member by name, including discriminated union cases, constants, or nested types.The leading
.resolves against the current scrutinee.Member payloads may supply nested subpatterns matching the member’s parameter list, e.g.
.Identifier(text)orResult<int, string>.Error(let message).Parentheses are optional for parameterless members.
Payload arity must match the declared parameters.
Each nested subpattern is typed to the corresponding member parameter.
A payload element introduces a new binding only when it uses
let/var(valis also accepted). Comparing with an existing in-scope runtime value requires== value.- Example:
.Case(let a, == b)bindsaand matches the second payload against the runtime value of in-scopeb.
- Example:
A trailing whole-pattern designation may capture the matched member/case value:
.Case(...) caseValue.Use
_to explicitly discard a payload.
Union case patterns
Body-form unions synthesize named case types, and those cases may be matched using three equivalent forms. The unqualified case form is the default pattern syntax; the qualified and target-typed forms are alternatives for disambiguation or stylistic clarity:
Case(...)orCase— unqualified case pattern. This is the default form when the case name is unambiguous for the scrutinee's union case set.Union.Case(...)— explicitly qualified union-member form..Case(...)— target-typed/member shorthand when the scrutinee determines the union.
For a case carrying a single unit payload, a bare Case pattern is sugar for
Case(()).
Parenthesized unions do not synthesize case names. They are matched using the ordinary pattern for one of their declared variant types:
union Payment(Cash | Card)
let description = match payment {
Cash(let amount) => "cash $amount"
Card(let reference) => "card $reference"
}
The carrier and its contained value remain distinct pattern targets. Matching
the carrier type itself, such as payment is Payment, tests the union instance.
A variant-type property pattern such as
payment is Card { Reference: let reference } let card first extracts the
active Card through the carrier and then applies the recursive property
pattern; the whole-pattern designation receives the extracted Card value.
Pattern combinators
pattern1 and pattern2— conjunction. Succeeds only when both operands match. Bindings from either operand are available after the conjunction.pattern1 or pattern2— alternative. Matches when either operand matches.not pattern— complement. Succeeds when the operand fails.notnever introduces bindings.
Precedence: not > and > or. or associates left-to-right. Parentheses
override precedence.