[!NOTE]
I'd like to continue to update this if it is necessary. This issue currently reflects what we have (in #293).
I'm trying to refactor what ideas we have based on the layering idea. This is also an answer to #305, #281
By layering, I do not mean we must have all features in layer 1 or must defer all features in layer 2.
This layering mostly focused on syntax, not runtime semantics.
I'll analyze this based on whether we can desugar a pattern into the composition of other patterns. (So you'll find the Primitive pattern (1 in { x: 1 }) is in Layer 2.)
This means we can pick all features from Layer 0 and some features from Layer 1 and 2, then the results become a somewhat usable pattern-matching proposal. (You may want to take a look at https://github.com/codehag/pattern-matching-epic).
I include:
all "future extensions" (= do not expect it will be in the final proposal, marked by π€)
features without consensus (might be incorrect!) (also marked by π€)
Non-pattern structures
Level 0: Basic feature
We should have at least one of them to enter the pattern world.
match expression (match (expr) { ... })
basic clause (when, or no keyword at all) (when <pattern>: <expr>, or <pattern>: <expr>)
basic clause with guard (when <pattern> if (<expr>): <expr>, or <pattern> if (<expr>): <expr>)
π¬ desugar: can be removed if we have the if pattern
default clause (default: <expr>)
if clause (if (<expr>): <expr>)
π¬ desugar: can be removed if we have the if pattern
is expression
π¬ desugar: impossible if the is expression enables the possibility to declare a new variable inside an expression
β οΈ concern: block scoped declaration { if (!(x is [let a, let b])) return; f(a, b) }
Level 1: Good to have
Maybe future extensions.
if-let (and also for, while, do-while)
based on the is expression
or something else like if match <pattern> (expr) {}
I'm trying to refactor what ideas we have based on the layering idea. This is also an answer to #305, #281
By layering, I do not mean we must have all features in layer 1 or must defer all features in layer 2.
This layering mostly focused on syntax, not runtime semantics.
I'll analyze this based on whether we can desugar a pattern into the composition of other patterns. (So you'll find the Primitive pattern (
1
in{ x: 1 }
) is in Layer 2.)This means we can pick all features from Layer 0 and some features from Layer 1 and 2, then the results become a somewhat usable pattern-matching proposal. (You may want to take a look at https://github.com/codehag/pattern-matching-epic).
I include:
Non-pattern structures
Level 0: Basic feature
We should have at least one of them to enter the pattern world.
match
expression (match (expr) { ... }
)when
, or no keyword at all) (when <pattern>: <expr>,
or<pattern>: <expr>
)when <pattern> if (<expr>): <expr>,
or<pattern> if (<expr>): <expr>
)if
patterndefault
clause (default: <expr>
)if
clause (if (<expr>): <expr>
)if
patternis
expressionis
expression enables the possibility to declare a new variable inside an expression{ if (!(x is [let a, let b])) return; f(a, b) }
Level 1: Good to have
Maybe future extensions.
if-let
(and alsofor
,while
,do-while
)is
expressionif match <pattern> (expr) {}
Pattern
Level 0: Basic features, impossible to desugar
expected_value
)π¬ desugar with custom matcher: write a function to match the value{ a: expected_value }
)π¬ desugar with custom matcher: write a function to match the shape and return value as an array{ __proto__: f }
means property__proto__
(owned or on the prototype) or[[Prototype]]
or early errors?{ [Symbol.iterator]: f }
) adds arbitrary expression interpolation{ x }
) means{ x: x }
or{ x: let x }
?{ ...x }
) means{ ...x: x }
or{ ...x: let x }
?{ a: let x }
)Level 1: Advance features, impossible to desugar
${expression}
){ id: let id, b: `id-${id}` }
)`a-${let x}-z`
matchesa-99-z
and bindx
to"99"
.[1, 2]
){ 0: let a, 1: let b }
.Array(let a, let b)
.{ x: Point }
) and extractor pattern ({ x: Point(let x, let y, let z) }
){ x: ${SomeFun(param)}(let a, let b) }
{ x: Point }
will call user code or do=== Point
check until runtime=== Point
checkif
pattern andand
pattern{ x: let x and if (x === Point) }
===
relational pattern{ x: === Point }
and
pattern (Map and { size: 1 }
){ a: Point and let a }
=>{ a: Point, a: let a }
&&
or
pattern (1 or 2
)||
not
pattern (not 1
)!
if
pattern (if (expr)
)is
expression{ a = 1 }
)Level 2: Ergonomic features
null
,true
,1
,2n
,"str"
,NaN
,`abc`
)let x = ...;
somewhere then match againstx
undefined
+1
-1
+1n
-1n
, π€+Infinity
, π€-Infinity
)+Infinity
and-Infinity
+0
,-x
)a + 1
/a/
)let x = ...;
somewhere then match againstx({ groups: { ... } })
/a(?<let name>)/
)/a(?<name>)/({ groups: { let name } })
{ value: Number.POSITIVE_INFINITY }
, π€{ x: Array[Symbol.iterator] }
)let x = ...;
somewhere then match againstx
[[Get]]
of"POSITIVE_INFINITY"
onNumber
?ident[expr]
syntax){ let x }
){ x: let x }
let { x, y }
){ x: let x, y: let y }
>= 2
)if
pattern andand
pattern:let x and if (x > 20 && x < 30)
> 2
,< 2
instanceof x
=== x
{ constructor: === Point }
"x" in
{ x: "a" in }
typeof "x"
{ x: Number }
, not{ x: typeof "number" }
{ a: 1, b: void }
){ a: 1, b: let _ }
using
.{ a: 1, b?: 2 }
)or
):{ a: 1 } or { a: 1, b: 2 }
{ a: 1, b = undefined }
{ let a: Number }
)and
):{ a: Number and let a }