在下面的示例程序中,有什么方法可以避免定义map2
?
fn map2<T, U, V, F: Fn(T, U) -> V>(f: F, a: Option<T>, b: Option<U>) -> Option<V> {
match a {
Some(x) => match b {
Some(y) => Some(f(x, y)),
None => None,
},
None => None,
}
}
fn main() {
let a = Some(5);
let b = Some(10);
let f = |a, b| {
a + b
};
let res = map2(f, a, b);
println!("{:?}", res);
// prints Some(15)
}
对于那些也会说Haskell的人,我想这个问题也可以表达为“我们可以在Rust中使用任何工具代替liftM2吗?”
答案 0 :(得分:15)
我不相信有一个等同于liftM2
的直接函数,但您可以将Option::and_then
和Option::map
组合在一起:
fn main() {
let a = Some(5);
let b = Some(10);
let f = |a, b| {
a + b
};
println!("{:?}", a.and_then(|a| b.map(|b| f(a, b))));
}
输出:
Some(15)
答案 1 :(得分:6)
从Rust 1.46.0开始,您可以使用Option::zip
:
fn map2<T, U, V, F: Fn(T, U) -> V>(f: F, a: Option<T>, b: Option<U>) -> Option<V> {
match a.zip(b) {
Some((x, y)) => Some(f(x, y)),
None => None,
}
}
这可以与Option::map
结合使用,如其他答案所示:
fn map2<T, U, V, F: Fn(T, U) -> V>(f: F, a: Option<T>, b: Option<U>) -> Option<V> {
a.zip(b).map(|(x, y)| f(x, y))
}
答案 2 :(得分:5)
我不知道你是否可以归结为一行(编辑:哦,接受的答案很好地将其归结为一行),但你可以通过匹配元组来避免嵌套def myRound(x):
r = x % 1
if r < 0.5:
return x-r
else:
return x-r+1
:< / p>
match
答案 3 :(得分:4)
您可以使用Option
s可以迭代的事实。迭代这两个选项,将它们压缩在一起,并将生成的迭代器映射到您的函数上。
fn main() {
let a = Some(5);
let b = Some(10);
let f = |(a, b)| {
a + b
};
let res = a.iter().zip(b.iter()).map(f).next();
println!("{:?}", res);
// prints Some(15)
}
这需要修改f
,因此参数合并为单个tuple-argument。通过直接映射f
,可以在不修改|args| f.call(args)
的情况下进行,但您必须specify the closure kind of f
。
答案 4 :(得分:4)
您可以将immediately invoked function expression (IIFE)与?
(尝试)运算符结合使用:
fn main() {
let a = Some(5);
let b = Some(10);
let f = |a, b| a + b;
let res = (|| Some(f(a?, b?)))();
println!("{:?}", res);
}
将来,您可以使用 try块:
#![feature(try_blocks)]
fn main() {
let a = Some(5);
let b = Some(10);
let f = |a, b| a + b;
let res: Option<_> = try { f(a?, b?) };
println!("{:?}", res);
}
另请参阅:
答案 5 :(得分:0)
let num_maybe = Some(5);
let num_maybe2 = Some(10);
let f = |a, b| {
a + b
};
if let (Some(a), Some(b)) = (num_maybe, num_maybe2) {
f(a, b)
}
num_maybe.and_then(|a| num_maybe2.map(|b| f(a, b))
[num_maybe, num_maybe2].into_iter().flatten().fold(0, f)