As you mention, it's hard to provide a fully-generic solution because we don't yet have generics over different tuple lengths. A library could use a macro to generate implementations up to some max length.
First I would review my code, looks like you doing something you should not do. Later create a macro to convert a tuple of N into a Vec, then copy paste macros increasing the tuple size until the amount I need.
On the note of macros, you could make a macro to do this (in large part thanks to hygienic macros)! playground (The only downside is that you can't pass in a tuple directly, you must pass in a list of options)
"First I would review my code, looks like you doing something you should not do."
So, I have two bits of XML -- and IRI and a data literal. The IRI I need to find a type definition for, so I can then convert it into another type, and the literal needs to be converted to a int; both of these can fail. If they both succeed, I want to produce a struct of a third type.
Imagine I have an infix expression evaluator.
let t = ("1", "+", "1");
let ct = (to_int(t.0), to_op(t.1), to_int(t.2))
let opt_expr = convert(ct);
// Should return either 2 in this case, but could return "None".
opt_expr.map(|expr| evaluate(expr))
Hmm, yes, you may be right. Instead of tuples, I can chain together calls to closures with and_then. A slightly noisy example, but....
let x = "1";
let y = "2";
println!("{:?}",
x.parse::<i32>().ok().and_then(
|xN| y.parse::<i32>().ok().and_then(
|yN| Some(xN + yN)
)
)
);
Adds the numbers, or returns None. Does not need to use a tuple to do the "has everything succeded" checked, and passes the intermediate results through the closures.
Or a simpler solution still, is to use the ? operator. It's slightly complex because I want an expression not a function, so I need to use closures.
I ended up macro'ing the whole thing, doing something like @mbrubeck's try based solution, but adding in the return of an Option. I think this is a nice solution without so many brackets and symbols.
macro_rules! some {
($body:expr) => {
(|| {Some($body)})()
}
}
fn main() {
let x = "1".parse::<i32>().ok();
let y = "2".parse::<i32>().ok();
println!("{:?}", || -> Option<i32>{Some(x? + y?)}());
println!("{:?}", some!{x? + y?});
}