This post tries to merge the recent discussion about push, append & pop (later on truncate) methods for arrays and the late-2020 to early-2021 discussion about push & append being language syntax.
My point is to discuss whether to wait for better const expressions and get those methods into core, create an expansion syntax that does not collide with the range syntax, or overloading arithmetic operators. For the syntax, my proposals are:
-
[...array, element1, element2]
, with chaining[...array1...array2, element1, element2]
: new three-dots syntax. -
[array @ .. element1, element2]
, with chaining[array1 @ .., array2 @ .., element1, element2]
: overloaded at-range syntax.
The latter would integrate much more that syntax into the language, since now it is very niche, and I haven't seen much people who know about it. However, the three-dots one seems much more readable and is more pleasant for chaining & concatenating, which, at the end of the day, is one of the main points of the first discussion.
If this option is chosen, we could also implement it in tuples, and be able to call functions like this:
fn foo(x: i32, y: u32) -> i32 {
unimplemented!()
}
fn bar(x: i32, y: u32, z: &str) -> String {
unimplemented!()
}
fn baz(x: i32, y: u32, z: i128, a: usize) -> i128 {
unimplemented!()
}
let tuple1 = (1i32, 2u32);
let tuple2 = (10i128, 5usize);
let a = foo(...tuple1); // three-dots syntax
let a = foo(tuple1 @ ..); // at-range syntax
let b = bar(...tuple1, "bar"); // three-dots syntax
let b = bar(tuple1 @ .., "bar"); // at-range syntax
let c = baz(...tuple1...tuple2) // three-dots syntax
let c = baz(tuple1 @ .., tuple2 @ ..) // at-range syntax
Personally, I don't like creating new niche syntaxes (we would be repeating the issue I just talked about when discussing the at-range), so as much as I like the three-dots, I vote for the at-range.
The last option would be overloading core::ops::Add
with a const impl for every of the following:
-
[T; N] + [T; L]
, [T; N] + T
T + [T; N]
Although I don't see this last option very coherent since:
- In rust, patterns are much more idiomatic than overloading.
- Truncate can't be nicely implemented overloading
core::ops::Sub
since there's no way to select the end to truncate. The only possible way would be by selecting the end based on the position of the array in the subtraction expression, which seems rather confusing and quite error-prone. However, it aligns with the2 - 1
!=1 - 2
principle.
And they would still require const expressions...