xilem icon indicating copy to clipboard operation
xilem copied to clipboard

Support arrays (`[impl ViewSequence; N]`) as `ViewSequence`s

Open Philipp-M opened this issue 1 year ago • 7 comments

Adds the blanket impl impl<const N: usize, VT: ViewSequence> ViewSequence for [VT; N]

Allows for example something like this:

fn my_tab(impl View) -> impl View {..}
h_stack(["Tab 1", "Tab 2", "Tab 3"].map(my_tab))

Philipp-M avatar Feb 16 '24 23:02 Philipp-M

Well I guess I'm getting too used to using unstable Rust ([].each_ref() is unstable in 1.76). But fortunately as I've just seen, the corresponding feature was just stabilized 3 weeks ago. So we can just wait for the next Rust version (1.77) and then the feature would be supported (when we don't want to try to keep MSRV low anyhow).

Otherwise this needs I think a more dynamic solution (State = Vec<VT::State>).

Philipp-M avatar Feb 16 '24 23:02 Philipp-M

Your comment made me curious and I looked into [].each_ref(), but I wasn't able to figure out what the benefit over for example [].iter().map(..m) is, especially in this case where the created array of references isn't kept around afterwards. What do you think is the benefit?

zoechi avatar Feb 20 '24 05:02 zoechi

each_ref allows to create a different array with the same size ([T; N].each_ref() -> [&T; N].map() -> [S; N]). The difference would be that Vec needs an allocation, while [T; N] does not. I don't expect much of a practical difference, and it could well be done with a Vec (via iter().map().collect()) instead (but I think it's a little bit cleaner with a static array).

Philipp-M avatar Feb 20 '24 12:02 Philipp-M

I see. Because the resulting array is not used (as far as I see), there also would be no Vec and collect() necessary.
My approach would be [].iter().for_each(|x| ...). https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2ad60536d7f403943d34758c29a01083 It's a bit more verbose though.

zoechi avatar Feb 20 '24 17:02 zoechi

Note the function signature of ViewSequence::build(&self, cx: &mut Cx, elements: &mut Vec<Pod>) -> Self::State Which returns the view state. So you need to create and return an owned container, it's not enough to just iterate over the child view sequences and invocate build().

It is used in every rebuild and message invocation, where it is handed by the parent/owning view sequence.

Philipp-M avatar Feb 20 '24 17:02 Philipp-M

Now I get it. I thought I checked 3 times if the result is returned and I didn't see it🤦🏼‍♂️

zoechi avatar Feb 20 '24 18:02 zoechi

The relevant feature is now in stable rust. So this is ready. We could increase the Rust version in a separate PR as well...

Philipp-M avatar Mar 25 '24 14:03 Philipp-M

Sorry, this probably has suffered the same fate at the hands of #310 as the other PRs

DJMcNab avatar Jun 17 '24 08:06 DJMcNab

I've updated this to the new xilem_core. Hmm I hope this doesn't suffer the same fate again though... I copied some of the tests from the tuple sequence, since they're seemingly equivalent from what needs to be tested.

Philipp-M avatar Jun 23 '24 17:06 Philipp-M

I'm not really sure how useful this is, but it also doesn't cost us anything to support.

Yeah I think it's mostly useful to avoid the more elaborate (and inefficient) version with Vec and small "hardcoded" arrays with the example in the comment in the PR description. But probably really not super-important to have, though I think we should support all (builtin) data structures that make sense as a ViewSequence.

Philipp-M avatar Jun 24 '24 09:06 Philipp-M

Thanks for the quick review, I'm merging.

Philipp-M avatar Jun 24 '24 09:06 Philipp-M