Skip to content

Instantly share code, notes, and snippets.

@gafter
Last active April 4, 2018 19:21
Show Gist options
  • Select an option

  • Save gafter/628e0db1032693c8e933d1afb4543f32 to your computer and use it in GitHub Desktop.

Select an option

Save gafter/628e0db1032693c8e933d1afb4543f32 to your computer and use it in GitHub Desktop.
2018-04-04 C# LDM Issues in Pattern-Matching

Order of evaluation in pattern-matching

Giving the compiler flexibility in reordering the operations executed during pattern-matching can permit flexibility that can be used to improve the efficiency of pattern-matching. The (unenforced) requirement would be that properties accessed in a pattern, and the Deconstruct methods, are required to be "pure" (side-effect free, idempotent, etc). That doesn't mean that we would add purity as a language concept, only that we would allow the compiler flexibility in reordering operations.

Resolution 2018-04-04 LDM: confirmed: the compiler is permitted to reorder calls to Deconstruct, property accesses, and invocations of methods in ITuple, and may assume that returned values are the same from multiple calls. The compiler should not invoke functions that cannot affect the result, and we will be very careful before making any changes to the compiler-generated order of evaluation in the future.

Range Pattern

If we have a range operator 1..10, would we similarly have a range pattern? How would it work?

    if (ch is in 'a' to 'z')
    switch (ch) {
        case in 'a' to 'z':

Discussion 2018-04-04 LDM: Keep this on the back burner. It is not clear how important it is. We would want to discuss this in the context of also extending other constructs:

from i in 1 to 100 select ...

foreach (var i in 0 to s.Length-1) ...

var deconstruct pattern

It would be nice if there were a way to pattern-match a tuple (or Deconstructable) into a set of variables declared only by their designator, e.g. the last line in this match expression

    var newState = (GetState(), action, hasKey) switch {
        (DoorState.Closed, Action.Open, _) => DoorState.Opened,
        (DoorState.Opened, Action.Close, _) => DoorState.Closed,
        (DoorState.Closed, Action.Lock, true) => DoorState.Locked,
        (DoorState.Locked, Action.Unlock, true) => DoorState.Closed,
        var (state, _, _) => state };

(Perhaps not the best example since it only declares one thing on the last line)

This would be based on some grammar like this

var_pattern
    : 'var' variable_designation
    ;

where the variable_designation could be a parenthesized_variable_designation, i.e. generalizing the current construct.

To make this syntactically unambiguous, we would no longer allow var to bind to a user-declared type in a pattern. Forbidding it from binding to a constant would also simplify things, but probably isn't strictly necessary.

I’m suggesting this now because at a recent LDM it was suggested that var could perhaps be used as a placeholder for an unknown type taken from context. But that would conflict with this usage because this usage changes the syntax of what is permitted between the parens (designators vs patterns).

This is implemented in the current prototype, in which var is now a contextual keyword.

Resolution 2018-04-04 LDM: YES! Approved.

ref/lvalue-producing pattern switch expression

As currently designed, the “switch expression” yields an rvalue.

    e switch { p1 when c1 => v1, p2 when c2 => v2 }

@agocke pointed out that it might be valuable for there to be a variant that produces a ref or an lvalue.

  1. Should we pursue this?
  2. What would the syntax be? e switch { p1 when c1 => ref v1, p2 when c2 => ref v2 }

Discussion 2018-04-04 LDM: Lets keep this on the back burner and see if there are requests based on actual use cases.

switching on a tuple literal

In order to switch on a tuple literal, you have to write what appear to be redundant parens

switch ((a, b))
{

It has been proposed that we permit

switch (a, b)
{

Resolution 2018-04-04 LDM: Yes. We discussed a couple of ways of doing this, and settled on making the parens of the switch statement optional when the expression being switched on is a tuple literal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment