, which works well (I can do v.expect_one().unwrap_or_else(|| panic!(...), but this seems like a very common pattern, so I'm wondering if there's a common way to do this?
A long time ago I wrote the single crate, missing the similar functionality from Kotlin, although that's limited to iterators, not vectors/slices directly. Nowadays itertools' at_most_one would be what to use.
Rather than expect_one as a helper, though, I'd suggest just writing the pattern inline when you need it, e.g.
let [e] = &v else {
panic!();
};
or better yet, avoid taking/building a slice in the first place.
No, that makes sense and is useful context. I'm processing an AST (actually, a Pandoc AST), and I want to extract data from some stuff that could be multiple items, but in my case it must be one.
For example, a table title is a vector of inlines, but I'm looking for table titles which are a single word, so a vector with a single inline.
@CAD97 Thanks! I think actually exactly_one is exactly what I need? I'm a bit puzzled about your other suggestion. Now, I'm a Rust noob and some basic stuff eludes me... I think given my use case exactly_one is best, but I'm unsure of the advantages of the pattern match?
, where I guess I can replace .expect_one() with .iter().exactly_one() and be on my merry way, whereas the match you suggest would be a bit wordier?
I'm having issues because I'm lately writing a lot of code that matches on non-trivial structures (esp. with vectors) and I'm sure there are more compact and clearer ways to do it...
If you can continue the chain, a postfix method will be a bit more "clean" and "point free" (no extra named bindings), but sometimes names, despite being a bit more extra verbosity, can improve code structure. The exact same written with a let-else:
fn parse_table_bodies(tables: &[pandoc::TableBody]) -> Vec<Vec<String>> {
let [table] = tables else {
panic!("should have one table body, got {:?}", tables)
};
table.body
.iter()
.map(rows_to_vec_str)
.collect()
}
At that point it's mostly just a matter of style. Except to note that if you use into_iter instead, you might be able to eliminate some cloning.