[fine] Notes on patterns

This commit is contained in:
John Doty 2024-02-04 19:13:56 -08:00
parent deed9d9a45
commit e0721d09fc

View file

@ -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" so we know that e.g. `<` or whatever means "generic type parameter"
and not "less than". 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" <expression>)?
```
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 ## Lambdas/Closures/Anonymous Functions
Looking for a syntax here; I want to keep `fun` as a declaration like Looking for a syntax here; I want to keep `fun` as a declaration like