rust替换函数名

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rust替换函数名相关的知识,希望对你有一定的参考价值。

1、函数简介
①、Rust 的函数使用关键字 fn 开头,函数名称使用snake case规范风格(所有字母小写并使用下划线分隔);

②、可以有一系列的输入参数,可以有一个返回值;

③、函数返回可以使用 return 语句,也可以使用表达式(末尾不带分号);

④、函数也可以不写返回类型,这种情况下,编译器会认为返回类型是unit();

⑤、可执行程序的入口是 fn main();

⑥、调用函数时,Rust不关心函数定义在哪(前后都无所谓),只要定义了就行;

⑦、Rust 函数体内可以定义其它模块,比如静态变量、常量、函数、trait、类型等。

2、函数实例
fn main()
let num = add(1,2);
println!("",num)


fn add(x:i32,y:i32) -> i32
x+y

登录后复制
3、函数返回值
需要注意语句和表达式的区别,表达式没有分号,有返回值。语句结尾有分号,没有返回值。

所以对于如下函数,如果函数体加上分号,则会报错:

fn add(x:i32,y:i32) -> i32
x+y;

登录后复制
把 x+y; 变成表达式即可(去掉末尾的分号)。

4、发散函数
Rust 支持一种特殊的发散函数(Diverging functions),它的返回类型是感叹号 !。
如果一个函数根本就不能正常返回,那么它就可以这样写:

fn diverges() -> !
//panic! 会直接导致栈展开,所以这个函数调用后面的代码都不会执行,它的返回类型就是!
panic!("函数不能返回");

登录后复制
发散函数的最大特点:可以被转换成任意一个类型。

在Rust 中,有下列情况返回类型都是 !:

1.panic! 以及基于它实现的各种函数/宏,比如unimplemented!、unreachable!
2.死循环loop
3.进程退出函数std::process::exit以及类似的libc 中的exec一类函数。

5、const fn
函数可以用 const 关键字修饰,这样的函数可以在编译阶段被编译器执行,返回值也被视为编译期常量。

需要注意的是:const 函数是在编译阶段执行的,因此相比普通函数有很多限制,并非所有的表达式和语句都可以在其中使用。
参考技术A rust替换函数名

Rust 1.7.0的macro宏-语法分析和使用举例

macro 宏的概念在很多语言中都有。

通常情况下,宏的机制是在预编译阶段对已经定义的宏进行替换或者 expanded 展开 ,即:把宏按照名称替换成宏的内容。

Rust 中的宏,与众不同!

Rust中的宏,也是在预编译阶段进行处理。宏不仅仅是替换内容和展开,还可以像功能函数一样,接收参数、调用其他的宏。

一、简单的宏

宏的名称和功能函数名称很像,只不过在函数名称后面有一个叹号!

一个简单的宏定义和调用:

macro_rules! say_hello{  
   ()=>(  
       println!("Hello");  
   )  
}  

fn main(){  
  say_hello!()  
} 

解释一下:
macro_rules! 声明一个宏,say_hello 是宏的名字,say_hello后面是一对大括号,是宏的内容体。

大括号里面的=>前面的 ( ) 表示这个宏没有输入参数。
在这个宏内部,调用了另外一个宏 println!

在main()功能函数中调用宏。因为这个宏和调用的功能函数在一个文件中,所以不需要额外的导出和引入宏的声明。

当然,宏的内容体除了用 {}大括号之外,还可以使用 (); 和 [];

macro_rules! say_hello (
   ()=>(  
   println!("Hello");  
   )  
);
    macro_rules! say_hello [
       ()=>(  
       println!("Hello");  
       )  
    ];

? 注意:

  • 使用大括号的时候,大括号后面没有分号;
  • 而使用()和[]的时候,后面有一个分号。

?如果大括号{}有分号;或者()和[]没有分号都会编译错误。

? 注意:

另一个需要注意的是,宏的输入参数是包含在宏内容体内的!!!

二、带参数的宏

下面定义一个带参数的宏 print_hello

macro_rules! print_hello{
 ($msg:expr) =>(
                  println!("hello{}",  $msg);
               )
}

fn main(){
    print_hello!(",world!");
}

上面定义了一个 print_hello 宏,把上面的代码分解成 4 个部分:

第一个部分:宏声明

macro_rules! print_hello 
  • macro_rules! 是宏定义关键字,注意后面有 ! 叹号
  • 后面跟宏的名称 这是定义宏的名称

第二部分:宏的内容边界 {一对大括号}

macro_rules! print_hello {

}

第三部分:宏的内容 -大括号中的内容

大括号中的内容被称为 macro rule 宏规则。一个宏可以包含任意(0 -n)多个 macro rule 宏规则。

($msg:expr) =>( println!("hello{}",  $msg) );
($msg:expr) =>{ println!("hello{}",  $msg) };
($msg:expr) =>[ println!("hello{}",  $msg) ];

($msg:expr) => (  println!("hello{}",  $msg); );
($msg:expr) => {  println!("hello{}",  $msg); };
($msg:expr) => [  println!("hello{}",  $msg); ];

以上 6 句 作用完全一致!

宏规则的格式应该是这样的:

( ) => {  };
( ) => [  ];
( ) => (  );
  1. 每个宏规则有一个 => ;
  2. 在 => 左面的小括号是该规则的输入参数,里面的形式是一个 叫做 matcher 匹配器;
  3. 在 => 右面的括号里是宏的内容,需要被执行或者替换,叫做 transcriber 转换器,可以是语句、表达式等。

以上三行代码等同。

matcher 和 transcriber 会在 后面的文章中详细说明。

前面说过,宏的参数是包含在宏内容体内的!
对比一下功能函数的声明格式:

 fn fn_name(x:i32,y:u32){

 }

功能函数的输入参数通过 fn_name 后面的小括号传入,参数可能是 0 个或者多个,但是所有的参数一定是在这个括号中声明。

来看看这段代码:

macro_rules! foo {
    (x => $e:expr) => (println!("mode X: {}", $e));
    (y => $e:expr) => (println!("mode Y: {}", $e));
}

fn main() {
    foo!(x => 7);
    foo!(y => 3);
}

宏的输入不是通过参数列表传入的!而是通过 match 的方式进行查找或者匹配的。
当匹配到 x => 7 ,则执行 mode X: 7
当匹配到 y => 3 ,则执行 mode Y: 3

第四部分:宏调用

print_hello!(",world!");

调用方式,使用宏名称后面加!叹号,叹号后面跟一个括号表示输入参数。

以上是关于rust替换函数名的主要内容,如果未能解决你的问题,请参考以下文章

C的string.h里有没有字符串替换函数

如何用C中#define宏中的字符串常量替换函数名

RUST 0x02 函数与注释与控制流

我的js

Java 获取类名,函数名,行数

谢烟客---------Linux之脚本编程---函数