首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Rust中的Fn、FnMut 和 FnOnce都有什么区别?

在 Rust 中,Fn、FnMut和FnOnce是三个用于表示闭包类型的 trait。闭包是一种可以捕获其环境变量的函数。在创建闭包是会默认实现这几个 trait 中的一个。

以下是三个 trait 的区别:

?Fn:Fn是最基本的闭包 trait。它表示闭包可以捕获其环境变量的不可变引用。

?FnMut:FnMut表示闭包可以捕获其环境变量的可变引用。这意味着闭包可以修改其环境变量的值。

?FnOnce:FnOnce表示闭包只能调用一次。它表示闭包可以捕获其环境变量的所有权。这意味着闭包可以移动其环境变量的值。

以下是三个 trait 的一些示例:

//?Fn

let?add_one_closure?=?|x:?i32|?->?i32?{

let?y?=?10;

x?+?y

};

//?FnMut

let?add_two_closure?=?|mut?x:?i32|?->?i32?{

x?+=?2;

x

};

//?FnOnce

let?consume_string_closure?=?|s:?String|?->?String?{

println!("Consumed?string:?{}",?s);

s

};

输出结果:

Consumed?string:?Hello,?world!

总结:

?Fn:闭包可以捕获其环境变量的不可变引用。

?FnMut:闭包可以捕获其环境变量的可变引用。

?FnOnce:闭包只能调用一次,并可以捕获其环境变量的所有权。

选择哪个 trait 取决于闭包的用途。

??如果闭包只需要读取环境变量的值,则可以使用Fntrait。

??如果闭包需要修改环境变量的值,则可以使用FnMuttrait。

??如果闭包只需要使用环境变量的值一次,则可以使用FnOncetrait。

以下是一些使用建议:

??优先使用Fntrait,因为它是最通用的。

??只有在需要修改环境变量的值时才使用FnMuttrait。

??只有在需要使用环境变量的值一次时才使用FnOncetrait。

此外,Fn、FnMut和FnOnce还可以相互转换。

?Fn可以转换为FnMut和FnOnce。

?FnMut可以转换为FnOnce。

以下是转换示例:

//?Fn?->?FnMut

fn?add_one(x:?i32)?->?i32?{

let?y?=?10;

x?+?y

}

let?mut?add_one_fnmut:?FnMut(i32)?->?i32?=?add_one;

//?FnMut?->?FnOnce

fn?add_two(mut?x:?i32)?->?i32?{

x?+=?2;

x

}

let?add_two_fnonce:?FnOnce(i32)?->?i32?=?add_two;

从源码的角度看它们为什么能够转换:

pub?trait?FnOnce<Args:?Tuple>?{

...

}

pub?trait?FnMut<Args:?Tuple>:?FnOnce<Args>?{

...

}

pub?trait?Fn<Args:?Tuple>:?FnMut<Args>?{

...

}

从源码可以看出,Fn继承了FnMut,而FnMut又继承了FnOnce。这是类型逐渐泛化的过程,这就好像坤坤属于男人,男人属于灵长类一个道理。 Fn要求只能只能捕获环境变量,而FnMut不但捕获环境变量还需要修改环境变量,所以Fn一定能满足FnMut的条件。就像1是正整数,那么它必然也是整数。同样的,FnOnce要求拿到环境变量的所有权,如此一来,不管是Fn还是FnMut都是在没有所有权的基础上运行的,有了所有权那就是能无所无能了。因此,无论是Fn还是FnMut都可以

总结:

Fn、FnMut和FnOnce是三个用于表示闭包类型的 trait。选择哪个 trait 取决于闭包的用途。此外,Fn、FnMut和FnOnce还可以相互转换。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OTNFzGKxtxO6DpmBQv0NmGJw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com