rust 在返回闭包时写入选项的值有什么影响?

l0oc07j2  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(131)

在返回闭包时写入选项的值有什么影响?

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)
};
6pp0gazn

6pp0gazn1#

盒子是一种解决方案。但我还不知道两者的区别
作为基线,每个函数(匿名或非匿名)都有自己的具体类型,与所有其他函数不同。
然而,命名函数和非闭包匿名函数可以被强制为“函数指针”fn(args...) -> ret
如果你使用“单位技巧”,这就是第一个代码片段中的情况:

let _: () = closure;

要知道rustc决定了closure的具体类型是什么,它会告诉你:

found fn pointer `fn(i32) -> bool`

因此,由于这两个匿名函数都是静态的(它们实际上不关闭任何对象),编译器将它们都转换为函数指针。
这在第二个代码片段中不起作用,因为第一个分支创建了一个 actual closure,它不能被转换成函数指针(因为它不仅仅是一个函数,它也是数据),因此类型不匹配。
Boxing可以工作,因为它允许创建动态调度的类型为

Box<dyn Fn(i32) -> bool>

它们是兼容的。

qrjkbowd

qrjkbowd2#

我认为你的错误在于你假设两个闭包的类型都是

Fn(i32) -> bool

但那是一个特质,不是一个类型,每个闭包都有它自己的类型,即实现了上面的特质。

T: impl Fn(i32) -> bool

Box解决了这个问题,因为两者的类型都变为Box<dyn Fn(i32)->bool>

相关问题