danvil
November 23, 2022, 1:18am
1
What is the best way to have something like the ?
for just a single expression instead of the whole function?
Consider some deeply nested data structure with lots of optional fields:
struct Bar {
bar: Option<i32>,
zoo: Option<Option<i32>>,
}
struct Foo {
foo: Option<i32>,
bar: Option<Bar>,
}
If I would want to extract a member deep down I could write a function:
fn get_me_that_zoo(x: &Foo, fallback: i32) -> i32 {
x.bar?.zoo?.unwrap_or(fallback)
}
However writing those functions for every nested field is a bit cumbersome and doesn't feel quite right.
Is there an equivalent of ?
but just for a single line so I could write something like this:
fn process(x: &Foo) {
let q = value_or(x.bar?.zoo??, 42);
if TARZO == 9 {
println!("a {}", value_or(x.bar?.bar?, 43));
} else {
println!("bee {}", q / 2);
}
}
cuviper
November 23, 2022, 1:41am
2
Try blocks will let you do that, although you also need to be careful about moving the thing you unwrap, which is why I added as_ref()
here:
#![feature(try_blocks)]
fn process(x: &Foo) {
let q = value_or(try { x.bar.as_ref()?.zoo?? }, 42);
if TARZO == 9 {
println!("a {}", value_or(try { x.bar.as_ref()?.bar? }, 43));
} else {
println!("bee {}", q / 2);
}
}
A stable way for now is with IIFE , like (|| x.bar.as_ref()?.zoo?)()
. Note that I dropped the trailing ?
to return it as-is, otherwise you would have to re-wrap it (which try
blocks do implicitly).
3 Likes
H2CO3
November 23, 2022, 6:44am
4
Instead of an IIFE, you should use the .and_then()
combinator on stable, it's less convoluted and it was designed for this purpose:
fn get_me_that_zoo(x: &Foo, fallback: i32) -> i32 {
x.bar.as_ref().and_then(|b| b.zoo.flatten()).unwrap_or(fallback)
}
(Playground) .
2 Likes
danvil
November 23, 2022, 7:33am
5
Right, that works, too! For a deep data structure ?
just feels so much more succulent. Instead of a rather long winded one.and_then(|y| y.two).and_then(|y| y.three).four
I can just write one?.two?.three?.four
. I feels like a waste to allow ?
for "return", but not for "single expression", but try {}
sounds exactly like the solution to this issue.
H2CO3
November 23, 2022, 7:34am
6
For a deep data structure resulting in long chains, you should probably factor the code in question out into its own function anyway.
system
Closed
February 21, 2023, 7:34am
7
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.