qidao123.com技术社区-IT企服评测·应用市场
标题:
rust学习二十.13、RUST的函数指针fn和匿名函数
[打印本页]
作者:
张国伟
时间:
2025-4-10 18:55
标题:
rust学习二十.13、RUST的函数指针fn和匿名函数
函数指针是一个好东西。
一、简述
函数指针就是执行一段函数代码的指针。
根据官方的说法,函数指针实现了FnOnce,FnMut,Fn特质。
由于函数指针是一种数据类型,以是rustc允许它作为函数/方法的参数,如许就给步伐设计添加了不少的灵活性.
当我估摸着,rust设计者就是为了让rust能够适应潮水:在函数/方法中直接传递匿名函数/闭包
一个典型的带有函数指针的rust函数定义如下:
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 这种定义方式实在某种程度上更加符合我的头脑方式。 在java中,我们不能那么定义,最多只能定义一个函数接口为参数,比方: void Fight(Tool tool,Target tar)
它看起来不如rust来的那么明显。rust的定义能够让我立刻意识到这是函数指针参数(意味着这是一段代码)。
当然,只要乐意,应该也可以把函数指针以不那么明显的方式定义,后文有例子.
二、示例
fn add_one(x: i32) -> i32 {
x + 1
}
fn multiply_10(x: i32) -> i32 {
x * 10
}
type FnPointer = fn(i32,i32) -> String;
fn link(f: FnPointer, x:i32,y:i32) {
let dst= f(x,y);
println!("{}",dst);
}
/**
* 第一个参数是函数指针,fn指针实现了FnOnce,FnMut,Fn特质,所以可以接受匿名函数作为参数。
*/
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
fn 书本例子() {
let list_of_numbers = vec![1, 2, 3];
//利用rustc,象我这样的傻瓜也能写rust!
let list_of_strings: Vec<String> =
list_of_numbers.iter().map(|i| "0".to_owned()+&i.to_string()).collect();
println!("{:?}", list_of_strings);
let list_of_strings2: Vec<String> =
list_of_numbers.iter().map(ToString::to_string).collect();
println!("{:?}", list_of_strings2);
}
fn main() {
//封装再封装,就可以解决一些复杂问题,至于是否高效是另外一回事了.
let funcs=[add_one, multiply_10];
let numbers = [123, 233, 3232, 32334, 5333];
for i in 0..numbers.len() {
let answer1 = do_twice(funcs[0], numbers[i]);
let answer2= do_twice(funcs[1], numbers[i]);
println!("({}+1)*2= {},({}*10)*2={}",numbers[i],answer1,numbers[i],answer2);
}
// do_twice同时也能接受匿名函数,rust的解释:fn指针实现了FnOnce,FnMut,Fn特质,所以可以接受匿名函数作为参数。
println!("\n匿名函数也能被接受作为参数的演示....");
let answer3 = do_twice(|x| x * 2+99, numbers[0]);
println!("{}经过处理后等于{}",numbers[0],answer3);
// 书本例子,让我们感兴趣是类似java等语言的流式操作
书本例子();
//类型别名
let link_to = |x:i32,y:i32| x.to_string()+&y.to_string();
link(link_to, 123,899);
}
复制代码
上例根本模仿册本,主要演示两个问题:
1.函数指针如何定义
2.使用函数指针作为参数的函数,也能接收匿名函数为入仓
别的顺便演示了如何让函数指针看起来不那么明显(效果上类似java等一些语言),以下代码用于达成这个目的:
type FnPointer = fn(i32,i32) -> String;
fn link(f: FnPointer, x:i32,y:i32) {
let dst= f(x,y);
println!("{}",dst);
}
复制代码
假如函数指针比较复杂,也许用上别名也不错。
输出结果:
三、函数指针的替代方案
在函数/方法中除了可以通过指定函数指针的方式来传递函数,实在还有会合方式:
1.利用特质绑定+通用类型
2.还是特质绑定+通用类型,只不过是别的一种书写形式
3.使用特质对象+动态分发dyn
以下就是例子:
[code]/** * 函数指针的替代者1 -- 利用特质绑定 */ fn batmanString>(f:T) { let result=f(1094,101); println!("{}",result);}/** * 函数指针的替代者2 -- 特质绑定的简化写法,rust 1.13引入的trait bound syntax */fn eggman(f:impl FnOnce(i32,i32)->String) { let result=f(1094,103); println!("{}",result);}/** * 函数指针的替代者3 -- 使用特质对象 */fn pigman(f:&dyn Fn(i32,i32)->String) { let result=f(2094,103); println!("{}",result);}fn main(){ batman(|x:i32,y:i32| x.to_string()+&y.to_string()+" 黑蝙蝠侠
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4