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.
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) ...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.
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.
- Should we pursue this?
- 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.
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.