在返回闭包时写入选项的值有什么影响?
let value = Some(0);
let closure = if value.is_some() {
|value: i32| false
} else {
|value: i32| true
};
上面的代码没有产生编译错误但是下面的代码有编译错误原因是什么?
let closure = if let Some(option_value) = value {
|value: i32| option_value == value
} else {
|value: i32| true
};
他们都是不同的类型
`if` and `else` have incompatible types
no two closures, even if identical, have the same type
consider boxing your closure and/or using it as a trait object
Box是一种解决方案,但我还不知道两者之间的区别
let closure = if let Some(option_value) = value {
Box::new(move |value: i32| option_value == value)
} else {
Box::new(|value: i32| true)
};
2条答案
按热度按时间6pp0gazn1#
盒子是一种解决方案。但我还不知道两者的区别
作为基线,每个函数(匿名或非匿名)都有自己的具体类型,与所有其他函数不同。
然而,命名函数和非闭包匿名函数可以被强制为“函数指针”
fn(args...) -> ret
。如果你使用“单位技巧”,这就是第一个代码片段中的情况:
要知道rustc决定了
closure
的具体类型是什么,它会告诉你:因此,由于这两个匿名函数都是静态的(它们实际上不关闭任何对象),编译器将它们都转换为函数指针。
这在第二个代码片段中不起作用,因为第一个分支创建了一个 actual closure,它不能被转换成函数指针(因为它不仅仅是一个函数,它也是数据),因此类型不匹配。
Boxing可以工作,因为它允许创建动态调度的类型为
它们是兼容的。
qrjkbowd2#
我认为你的错误在于你假设两个闭包的类型都是
但那是一个特质,不是一个类型,每个闭包都有它自己的类型,即实现了上面的特质。
Box解决了这个问题,因为两者的类型都变为
Box<dyn Fn(i32)->bool>