Skip to content

Commit c91bbc6

Browse files
committed
fixed notation of RAP15
1 parent af0f0af commit c91bbc6

File tree

1 file changed

+34
-15
lines changed
  • courses/RascalAmendmentProposals/RAP15

1 file changed

+34
-15
lines changed

courses/RascalAmendmentProposals/RAP15/RAP15.md

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,33 @@ The proposal is to extend the Pattern notation like so:
1717

1818
The semantics is that if the `pattern` matches then we check if the boolean `condition` evaluates to true in the current environment (which includes optional bindings from the current pattern).
1919

20-
And to introduce short-hand notation for all binary predicate operators (==, \!=, :=, \!:=, \<, \<=, \>=, \>) like so:
21-
`syntax Pattern = Pattern pattern “==” Expression value`
22-
`| Pattern pattern “!=” Expression value`
23-
`| ...`
20+
And to introduce short-hand notation for all binary predicate operators (`==`, `!=`, `:=`, `!:=`, `<`, `<=`, `>=`, `>`) like so:
21+
22+
```
23+
syntax Pattern = Pattern pattern “==” Expression value`
24+
| Pattern pattern “!=” Expression value`
25+
| ...`
26+
```
2427

2528
And the short-hand expansion is:
2629
`p == v` expands to `tmp:p if tmp == v`
2730

31+
The `when` notation and semantics could be completely removed in time.
32+
2833
## Motivation
2934

3035
This RAP solves *a number of issues* in the design of Rascal’s syntax and semantics in one go:
3136

3237
* **Non-linear patterns (reused pattern variables)** often accidentally capture variables of the outer scope, leading to unexpected failure. This is one of the oldest issues in the design and has been mitigated by the checker providing info/warnings when it happens.
33-
* When-clauses are written out of the execution order
34-
* When-clauses are not allowed for functions with statement blocks as bodies
35-
* Randomized input for tests has to be filtered inside of tests, often returning `true` when the test input is invalid (and wasting opportunity for the valid input).
38+
* **When-clauses are written out of the execution order**
39+
* **When-clauses are not allowed for functions with statement blocks as bodies**
40+
* Randomized input for tests has to be filtered inside of tests code block, often returning `true` when the test input is invalid (and wasting opportunity for the valid inputs).
3641

37-
The urgency of this RAP is *low*. However, the non-linear matching issue has waited for more than 10 years now and it is still a weekly cause of time loss debugging this trivial issue in new code.
42+
The urgency of this RAP is *low*. However, the non-linear matching issue has **waited for more than 10 years now** and it is still a weekly cause of time loss debugging this trivial issue in new code. The type-checker warns about non-linear matches with an info message; which helps while writing new code, but it is a frequent source of false positives in the code that is left.
3843

39-
Also there are other ways to solve the nonlinear matching problem. For example by introducing specific syntax for it in the Pattern notation. The benefit of this new notation is that it fixes the non-linear matching problem but also other problems with “when” and with random tests.
44+
There are other ways to solve the nonlinear matching problem than to rename a variable. For example by introducing specific syntax for equality testing in the Pattern notation.
4045

46+
The benefit of the currently proposed new notation is that it fixes the non-linear matching problem but also other problems with “when” and with random tests.
4147
**It would be less nice if we have to add conditional patterns anyway and have added yet another syntax for non-linear matching.**
4248

4349
## Specification
@@ -54,7 +60,7 @@ Dynamic semantics:
5460

5561
* First the pattern is matched against the current subject; with optional bindings as a side-effect. Note that if the pattern is not singular, backtracking may occur later.
5662
* Then a new backtracking and binding scope is wrapped around the evaluation of the condition (such that complex back-tracking conditions can introduce variables and be cleaned up nicely)
57-
* The condition finds the first way to evaluate to true (includes possible backtracking over the original pattern, but certainly also over non-singular parameters of && and ||.
63+
* The condition finds the first way to evaluate to true (includes possible backtracking over the original pattern, but certainly also over non-singular parameters of `&&` and `||`. The semantics is comparable to the sematics of a `when` clause.
5864
* If there is no way to evaluate the condition to true, the entire pattern fails.
5965
* Otherwise the pattern succeeds and continues with the bindings introduced by the pattern side (and drops the new bindings introduced by the condition side).
6066

@@ -67,25 +73,37 @@ Test semantics
6773

6874
Short-hand notation
6975

70-
* Expanding `p == v` to `tmp:p if tmp == v` for every binary operator is simple.
71-
* Note how `_ == a` and `b := a` can be used for two different types of non-linear match. The first matches with equality (including keyword fields). The second matches with equality-modulo-keyword fields.
76+
* Expanding `p == v` to `tmp:p if tmp == v` for every binary operator. `tmp` must be fresh in the current scope, and unused in the succeeding scopes.
77+
* Note how `_ == a` and `_ := a` can be used for two different types of non-linear match. The first matches with equality (including keyword fields). The second matches with equality-modulo-keyword fields.
7278

7379
New static restrictions on patterns:
7480

7581
* Implicit nonlinear patterns are “duplicate declaration” errors:
76-
* so: `and(x, x)` is and error (second x is a duplicate declaration
82+
* so: `and(x, x)` is and error (second x is a duplicate declaration). Initially this should be a warning (not an info anymore) and a quickfix should be generated to expand the non-linear match to either `_ := x` or `_ == x`
7783
* Should be written as `and(x, _ := x) or and(x, _ == x)`
7884
* All variable introductions in patterns are “fresh” from now on, so the static semantics of:
7985
* `int x` is the same as
8086
* `x`
8187
* Except for the possibility of type inference in the latter.
8288

89+
Removing `when`
90+
91+
* Any application of when can always be rewriting to an application of `if` to the last parameter.
92+
* If an `if` uses only variables to the left, then it can be moved to earlier in the parameter list.
93+
* Only `when` clauses to functions without parameters can not be transformed,
94+
however, we are pretty sure that those do not exist. In any case they could be rewrittten to an `if` inside the body of the function or a `?:` expression.
95+
8396
## Examples
8497

8598
```
86-
// "dependent types"
99+
// simulating "dependently typed patterns"
100+
// because pattern matching is a runtime feature, we are no actually
101+
// introducing a dependently typed type-system (!) but we come close
102+
// to the same level of expressiveness.
87103
int fac(0) = 1;
88104
int fac(int n > 0) = fac(n - 1) * n;
105+
// without use of the shorthand:
106+
int fac(int n if n > 0) = fac(n - 1) * n;
89107
90108
bool evenOdd(int E if E % 2 == 0,
91109
int O if E % 2 == 1) = true;
@@ -106,9 +124,10 @@ This simplifies the implementation of the type-checker and the interpreter alike
106124
1. change the current informational message on nonlinear matches to a warning with suggestion for refactoring.
107125
2. Add warnings for all “when” clauses to be refactored to conditional patterns (if possible)
108126
3. Add warnings for tests that use `==>` for input filtering or `if(expression) return true;`
127+
4. Add simple quick-fixes to the warnings
109128
3. Then, in time, we remove the old semantics:
110129
1. Make non-linear matches produce double declaration errors
111-
2. Remove syntax and semantics of `when`
130+
2. **Remove syntax and semantics of `when`**
112131

113132
## Alternative solutions
114133

0 commit comments

Comments
 (0)