That was... not actually intended to use different syntax for the two 
I see a syntactic problem having both [0..3]: [1,2,3] and [10..20]: 7. How do you know that [1,2,3] is not a single array entry? Arrays of arrays are a thing, after all.
Furthermore Iām wondering if something similar could be (or become) possible with const fn resulting in syntax like the following (a better name for array_from_function is TBD):
let arr = array_from_function::<u32, 100>(|i| match i {
5 => 42,
8 => 123,
10..20 => 7,
21..=23 => [1,2,3][i-21]
0..3 | 98..100 => i+1,
_ => 0xDEADBEEF,
});
A const fn for initialization sounds great for lookup tables, e.g. gamma functions, ASCII case mapping. Syntaxes with literal values can't express them in a terse way.
I'm not sure about this, but thanks to const eval having the spelled out version of
let arr = {
let mut arr = [0; 100];
arr[1] = 3;
arr[40] = 42;
arr
};
we should produce the same machine code as
let arr: [u32; 100] = [0; 100; {
[..] = 0,
[1] = 3,
[40] = 42,
}];
right?
If (and only if) you use a const {} block to guarantee const evaluation of the rhs would this be guaranteed.
Thanks to all for the valuable feedback! Here's my second attempt implementing a better syntax, which you can use with array-lit v0.2.0:
const a: [i32; 8] = arr![0; 8; {
6: 1, // 1 at index 6
[2]: [3, 4], // 3 and 4 starting from index 2
7: 5, // 5 at index 7
}];
assert_eq!(a, [0, 0, 3, 4, 0, 0, 1, 5]);
It also got more powerful, so you can now insert runtime values (anything that implements Index):
let my_slice = &[1, 2, 3];
let a = arr![0; 8; { [1]: my_slice }];
assert_eq!(a, [0, 1, 2, 3, 0, 0, 0, 0]);
Unfortunately, this can't be const-evaluated, because it requires loops (see #52000).
The range syntax proposed by @Tom-Phinney and @steffahn is not supported, because that would make the macro_rules! implementation much more complicated. Instead, only the start of the range is needed.
Feedback is very much appreciated!
I really like that example, because it's already quite good on its own (assuming const{}), and thus pushes me away a bit from the set-lots-of-ranges special syntax.
Then it's just be a matter of const copy_from_slice for arr[3..=4].copy_from_slice(&[7, 8]), or potentially enabling arr[3..=4] = [7, 8]; with some form of destructuring assignment.
That's what I've seen as well, for things like unicode. Once it's at all complicated, there's a separate script to generate the literal. And if it's known to be particularly sparse, it's probably generating a format more optimized than a mostly-default slice.
Isn't the "equivalent" you're using here semantically more operations that necessary? I imagine LLVM optimizes out the unused writes with the initial fill, but optimizations aren't always a given.
Yes, but I'm not convinced that the difference matters in general. If it does, then you can use unsafe, because at that point you will likely need something more specialized than what syntax allows.
This is one of the advantages of move being only memcpy in rust, actually, as it makes it substantially more likely that such a thing happens. Add on to that that [x; n] requires Copy (or const), and this is the easiest possible situation for this kind of optimizations. (We could plausibly even do this in mir, I think.)
I think that the current fact that [x; n] requires Copy is strict negative (and annoyance).
Already it's moving towards also allowing x to be const-promotable (a special form of const evaluatable). [Vec::new(); N] will (eventually) work.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.