Tuple Helper Functions
I don't think we need to move forward with these just yet, it would be better to get some sort of variadic generics before these extensions.
fn zip<(A @ ..), (B @ ..)>((a: A) @ .., (b: B) @ ..)
-> ((A, B) @ ..)
{
((a, b) @ ..)
}
What happens if the two tuples are different lengths? Hint: it shouldn't be a post-monomorphization error, because that would run counter to how Rust handles generics.
fn all<T @ ..>((t @ ..): (T @ ..))
-> bool
where (T: Into<bool> + Copy) @ ..
{
(t.into() && ..)
}
It would be better if this took a closure as an argument, but that would require generics closures.
For generic type parameter IDENTIFIER@..
or (IDNTIFIER@..)
the identifier declares a type parameter pack
How would this interact with pattern matching? i.e. let x @ .. = ..;
is valid syntax right now, as is fn foo(x @ ..: ..)
at the very least, this should use ...
to get around this, but that will have to be bounded on an edition, because 3 dots is valid in patterns.
fn foo<A@..>(a: A@..) // => fn foo<A1, A2, B>(a1: A1, a2: A2)
fn foo<A@..>((a: A)@..) // => fn foo<A1, A2, B>(a1: A1, a2: A2)
fn foo<A@..>(a: (A@..)) // => fn foo<A1, A2, B>(a: (A1, A2))
Are these all missing a B
in the comments? Shouldn't it be
fn foo<A@..>(a: A@..) // => fn foo<A1, A2, B>(a1: A1, a2: A2, a3: B)
fn foo<A@..>(a: (A@..)) // => fn foo<A1, A2, B>(a: (A1, A2, B))
fn foo<A@..>((a: A)@..) // => fn foo<A1, A2, B>(a1: A1, a2: A2)
fn foo<(A@..)>(a: (A@..)) // => fn foo<(A1, A2), B>(a: (A1, A2))
I don't think that these should be valid syntax. For the first, I don't see the value in two different ways to express the exact same thing. For the second, I don't see the use case for it.
fn foo<A@.., B@..>((a: A)@.., (b: B)@..) // => ERROR: multiple type parameter packs
fn foo<(A@..), B@..>((a: A)@.., (b: B)@..) // => ERROR: multiple function argument expansions
instead of making these errors, we could say, in order to specify type parameter packs, you must provide a tuple. This also removes the need for the (A@..)
syntax, and makes things unambigious.
foo::<(A, B, C), (D, E, F)>
fn foo<A>((a@..): A) // => fn foo<(A1, A2)>((a1, a2): (A1, A2))
This should be an error, we should only allow unpacking type parameter packs, not normal generic parameters.
fn foo<A@(..)>(a: A) // => fn foo<(A1, A2)>(a: (A1, A2))
This seems to be closest to my desired syntax. (Which i will show at the end)
Implementation
I don't think we need to cover how to implement this, only how it is specified.
fn foo<A...>(a: A) { todo!() }
fn bar<A..., B...>(a: (...A), b: (...B)) { todo!() }
bar((0, "".to_string()), (0, Bar))