I am not a fan of the the ..#T
syntax, for several reasons:
- It would most definitely break the procedural macro of the
quote
crate - It's confusing when
T
is an array - It looks noisy
- It diverges from current syntax
- With variadic tuple expansion, it's inconsistent and obscures control flow
1. It would most definitely break the macro of the quote
crate
The quote
crate has a quote!
macro that substitutes tokens starting with a hashtag. It's used frequently for creating procedural macros.
2. ..#[T; n]
looks like an attribute
Although it might not cause a parse error, it's definitely weird to look at.
3. It looks noisy
Example from the RFC:
fn clone_add<(..#T)>((..#i): (..#T)) -> (..#T)
where ..#(T: Clone + Add) {
(..#(<T as Clone>::clone(&i) + i))
}
4. It diverges from current syntax
The syntax of destructuring a variadic tuple is different from destructuring a normal tuple or a struct:
let Foo { a, ..b } = normal_struct;
let Bar(a, ..b) = tuple_struct;
let (a, ..b) = tuple;
let (a, ..#b) = variadic_tuple;
I believe that this will make the feature harder to learn, understand, and use correctly.
5. With variadic tuple expansion, it's inconsistent and obscures control flow
Example from the RFC:
fn my_func<(..#T)>((..#i): (..#T)) {
(..#{ println!("{}", i) })
}
What is i
here? It's not a tuple, it's what is inside the tuple. But it isn't a value either. It's a special case, that doesn't exist anywhere else, and it can only be used in an expansion form (..#EXPRESSION
). I can only imagine how much effort this would be to implement in the compiler.
And what about the expansion form? It "desugars" into a tuple, and the content of the expansion form is repeated n times, where n is the arity of the tuple:
// if T has an arity of 3:
fn my_func<T1, T2, T3>((i1, i2, i3): (T1, T2, T3)) {
(
{ println!("{}", i1) },
{ println!("{}", i2) },
{ println!("{}", i3) },
)
}
This means that three values are printed, even though the function contains println!
only once, and doesn't have any loops. Also, the expansion form can't take ownership of a value in the function, because then there would be more than one owner. People will find this counter-intuitive.
It would be more intuitive to use a block that introduces the variable, so it has a well-defined scope. Something like:
fn my_func<(..#T)>(tuple: (..#T)) {
(repeat i in tuple {
println!("{}", i)
})
}
However, a macro might be more appropriate for this.
P.S. You're missing a T: Display
trait bound in the examples!