From e0721d09fcb99f01d331552b29fd13432b8ba266 Mon Sep 17 00:00:00 2001 From: John Doty Date: Sun, 4 Feb 2024 19:13:56 -0800 Subject: [PATCH] [fine] Notes on patterns --- fine/design.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/fine/design.md b/fine/design.md index df9cc5d8..444a0252 100644 --- a/fine/design.md +++ b/fine/design.md @@ -40,6 +40,78 @@ immediately following the `new` keyword is always a type expression, so we know that e.g. `<` or whatever means "generic type parameter" and not "less than". +## Patterns and Alternate Types + +Instead of `enums` or inheritance, we're using an alternate type like +in Typescript, with `or` between types. See the `alternates.fine` test +for a work-up of the types and syntax and whatnot. I think it works +pretty well. + +Actually using alternate types involves pattern matching, either one +at a time, with the `is` operator, or in bulk, with the `match` +expression. `match` can check for completeness, but `if/is` cannot. + +Patterns are VERY simple, and are explicitly *not* destructuring right +now. (Destructuring brings up a whole lot of complexity that I don't +want to deal with.) + +Patterns are basically: + +``` +(identifier ":")? type_expression ("and" )? +``` + +The identifier at the front represents a binding of the value being +considered as if it were of the same type as the type expression; the +identifier is in scope for the optional predicate after the "and" and +so you can use it as if it were the type because, well, that part of +the pattern already matched. + +As a special case, the identifier is *also* in scope for the body of +an `if` expression when an `is` expression is used as the condition. + +``` + if b is c:Foo { + result = result + c.a; // c should still be in scope! + } +``` + +`match` is the multi-value pattern matching expression, like this: + +``` + match b { + c:Foo -> c.a, + _ -> 0, + } +``` + +The special pattern `_` always evaluates to true. + +Note that unlike rust we do not allow variable binding, e.g., in rust you can write: + +``` + match b { + d -> ..., + } +``` + +but in fine you need to write: + +``` + match b { + d:_ -> ..., + } +``` + +The reason is that the rust version is ambiguous: if `d` matches some +value already in scope (e.g., an `enum` arm) then the arm is matching +if b == d, but if `d` is unbound then `d` becomes a variable +declaration. This is a spooky action-at-a-distance and I don't approve +of it. + + +# Complete Garbage + ## Lambdas/Closures/Anonymous Functions Looking for a syntax here; I want to keep `fun` as a declaration like