Add `this` and `infer` members to tuples
- Dominant language
- Python
- Stars
- 1
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Consider a tuple
```rs
bing : (foo: str, bar: i32)
```
Even though it contains a `str`, `bing` cannot be used as one without `.foo`.
However, it is sometimes desirable to allow a tuple to be used as one of its members, without having to add the explicit access.
This could be done with the addition of a new parameter modifier `this`. Initially this could be implemented as an attribute `#this` on parameters. When `this` is present on a parameter list `q : (this X, ...Y)`, it means that `q` can be used in place of something expecting `X`.
Additionally, a second modifier `infer` could be added which infers the requested parameter from context (or at least attempting to) when the tuple is created. Similarly this can be also done through an attribute `#infer`. In some ways, `infer` is the inverse of `this`: `this` is relevant for tuple destruction (on field access, ignoring the other fields), while `infer` is relevant for tuple construction (inferring the other fields). It is useful when you have a `x: X` and need to fulfil the type `(this X, infer Y)`: instead of providing `(x, get_y_somehow())` you could provide `x` and expect that due to the presence of `infer`, `get_y_somehow()` will be inferred. Of course, the inference is a best-effort, and if it fails the compiler will request the parameter to be added manually.
Why is any of this needed or useful? See the use cases below.
## Use cases
### Struct inheritance
```rs
Animal := struct (age: Age)
Cat := struct (this Animal, meow: Sound) // could also write (this animal: Animal, ..)
c := Cat(..)
c.meow : Sound
c.age : Age
alloc_animal := (a: Animal) => {..}
// Both valid
alloc_animal(c)
alloc_animal(c.0)
```
### Constraints
Consider an extension of the syntax where `P where Q` means `(this P, infer Q)`. This can be used to write constraints, with `Q` being inferred from context if possible.
```rs
AsType ((b) => type b ~ true)
arcsin : (x: f32) where { x in -1..1 } -> (r: f32) where { r in (-PI/2)..(PI/2) }
= (x) => { ... }
bing := (x: f32) => {
if x in -1..1 {
// implicitly exists: _p: {x in -1..1}
print(arcsin(x)) // desugared/inferred to print(arcsin((x, _p)))
}
}
```
### Traits
The expression `(T: Type) where Foo`, where `Foo` is a struct with a type parameter, can be used to write generics with trait bounds, where `Foo` represents a trait.
```rs
Iterator := struct (
next: &mut I -> Option
)
VecIter := struct (
data: &mut Vec,
current_index: usize
)
vec_iter_iterator := => Iterator , T> (
next = (v) => {
if v.current_index == len(v.data) {
None
} else {
result := v.data[v.current_index];
v.current_index += 1;
Some(result)
}
}
)
collect_nodes := > => (nodes: I) -> NodeCollection => {
...
}
build_ast := () => {
node_vec := vec()
// .. build the ast
nodes := collect_nodes(iter(node_vec))
// desugared to:
nodes := collect_nodes<(VecIter, vec_iter_iterator)>(iter(node_vec))
pass_to_next_stage(nodes)
}
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.