[fine] Notes on patterns
This commit is contained in:
parent
deed9d9a45
commit
e0721d09fc
1 changed files with 72 additions and 0 deletions
|
|
@ -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" <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
|
||||
|
||||
Looking for a syntax here; I want to keep `fun` as a declaration like
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue