as @SebastianJL pointed above, you cannot chaining callbacks returning arbitrary types, you need to make them returning Option
too.
JS is dynamically typed, and every value can be nullish
, so the chaining works for anything.
rust, on the other hand, is statically typed, only Option<T>
can be None
, so chaining is only valid when all the intermediate value down the chain are all Option
s.
ps:
rust have a similar ?' syntax too, but, in JS, the chaining operator is
?.` (it's one single operator, note the dot there), and they work very differently:
in javascript, if what you are chaining is not a method call or property access, you must use these oddly looking syntax:
// array index
var x = arr?.[42];
var arr = null;
// function call
var fun = null;
var x = fun?.();
// attributes, not lexical variable:
this.on_error?.()
in rust, the ?
operator is just sugar syntax for a match
expression, so it can be used anywhere an expression can be used, and it is not limited to Option
, notably, Result
can use the ?
syntax too. (for technical details,
see the Try
trait)
here's a trick if you want to use the ?
syntax but the current function does not return Option
, you can use a closure to set up a local type context for the ?
operator. for instance, the example code snippet by @SebastianJL can be rewritten as:
let x = Some(32);
// explicit types
let a: String = |x: Option<i32>| -> Option<String> {
let x = x?;
let x = f1(x)?;
let x = f2(x);
Some(x)
}(x)
.unwrap();
dbg!(a);
// alternative: use type inferrence, shorter
let a = |x| -> Option<_> { Some(f2(f1(x?)?)) }(x).unwrap();