Rust 函数详解

目录
  • 函数参数
  • 函数返回值
  • 高阶函数
    • 函数指针类型
    • 函数作为参数
    • 函数作为返回值
  • 相关资料

Rust 支持多种编程范式,但更偏向于函数式,函数在 Rust 中是“一等公民”,函数可以作为数据在程序中进行传递。跟 C、C++ 一样, Rust 也有一个唯一的程序入口 main 函数。

示例:程序入口 main 函数

fn main() {
    println!("Hello, world!");
}

Rust 使用 fn 关键字来声明和定义函数,使用 snake case 风格来命名函数,即所有的字母小写并使用下划线分隔单词。函数可以有参数,并且每个函数都有返回值。

函数参数

参数的声明方式:参数名 + 冒号 + 参数类型

示例

// 定义一个无参函数
fn function() {
    println!("A function with no parameters.");
}

// 定义一个有参函数
fn hello(name: &str) {
  println!("Hello, {}.", name);
}

函数返回值

在 Rust 中所有函数都有返回值,main 函数也不例外,main 函数的返回值是 ()(一个空的元组)。在 Rust 中,当一个函数返回 () 时,可以省略返回值类型的声明。main 函数的完整形式如下:

  fn main() -> () {
    //statements
  }

() 通常被称为 unit 或者 unit type,它其实类似于 C/C++、Java、C#中的 void 类型。

若函数有其他类型返回值,则需使用 -> 显式标明返回值类型。像 C/C++ 或 Java 等语言在函数中需要用 return 语句返回一个值,Rust 与它们不一样,Rust 默认将函数中最后一个表达式的结果作为返回值。

示例:定义一个有返回值的函数

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {}", x);
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

Rust 也有 return 关键字,不过一般用于提前返回。

示例:在函数中使用 return

fn main() {
  let a = [1,3,2,5,9,8];
  println!("There is 7 in the array: {}", find(7, &a));
  println!("There is 8 in the array: {}", find(8, &a));
}
fn find(n: i32, a: &[i32]) -> bool {
  for i in a {
    if *i == n {
      return true;
    }
  }
  false // 这里也可以改为 `return false;`,但这就不是 Rust 的编程风格了
}

在 Rust 中还有一种“没有返回值”的函数,称之为发散函数(diverging function)。其实,它根本就不返回,它使用感叹号 ! 作为返回类型。

示例

fn main() {
  println!("hello");
  diverging();
  println!("world");
}
fn diverging() -> ! {
  panic!("This function will never return");
}

发散函数一般都以 panic! 宏调用或其他调用其他发散函数结束,所以,调用发散函数会导致当前线程崩溃。

高阶函数

高阶函数与普通函数的不同在于,它可以使用一个或多个函数作为参数,可以将函数作为返回值。既然函数可以作为参数和返回值,那么函数也应该有一种相对应的数据类型,那就是:函数指针类型。

函数指针类型

函数指针类型使用 fn 关键字定义,在编译时该类型指向一个已知函数参数和返回值类型,但函数体未知的函数。

示例

// 函数定义
fn inc(n: i32) -> i32 {
    n + 1
}

// 使用 `type` 给函数指针类型起一个别名
type IncType = fn(i32) -> i32;

fn main() {
    // 使用函数指针类型 `fn(i32) -> i32`
    let func: fn(i32) -> i32 = inc;
    println!("3 + 1 = {}", func(3));

    // 使用函数指针类型的别名 `IncType`
    let func: IncType = inc;
    println!("4 + 1 = {}", func(4));
}

函数作为参数

函数作为参数,其声明与普通参数一样。

示例:高阶函数

fn main() {
  println!("3 + 1 = {}", process(3, inc));
  println!("3 - 1 = {}", process(3, dec));
}
fn inc(n: i32) -> i32 {
  n + 1
}
fn dec(n: i32) -> i32 {
  n - 1
}
// process 是一个高阶函数,它有两个参数,一个类型为 `i32`,另一个类型为 `fn(i32)->i32`
fn process(n: i32, func: fn(i32) -> i32) -> i32 {
  func(n)
}

函数作为返回值

函数作为返回值,其声明与普通函数的返回值类型声明一样。

示例

fn main() {
    let a = [1,2,3,4,5,6,7];
    let mut b = Vec::<i32>::new();
    for i in &a {
        b.push(get_func(*i)(*i));
    }
    println!("{:?}", b);
 }

 // 若传入的参数为偶数,返回 `inc`,否则返回 `dec`
 fn get_func(n: i32) -> fn(i32) -> i32 {
    fn inc(n: i32) -> i32 {
        n + 1
    }
    fn dec(n: i32) -> i32 {
        n - 1
    }
    if n % 2 == 0 {
        inc
    } else {
        dec
    }
}

相关资料

Rust Programming Language

The Rust Reference

Rust By Example

RustPrimer

到此这篇关于Rust 函数的文章就介绍到这了,更多相关Rust 函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Rust 中的文件操作示例详解

    目录 文件路径 文件创建和删除 目录创建和删除 文件创建和删除 文件读取和写入 文件打开 文件读取 文件写入 相关资料 文件路径 想要打开或者创建一个文件,首先要指定文件的路径. Rust 中的路径操作是跨平台的,std::path 模块提供的了两个用于描述路径的类型: PathBuf – 具有所有权并且可被修改,类似于 String. Path – 路径切片,类似于 str. 示例: use std::path::Path; use std::path::PathBuf; fn main()

  • C++的替代:微软如何使用rust?

    微软拥有世界上最大的C/C++代码库之一.从Windows.Office到Azure云,微软的所有核心产品都在该代码库上运行.但因为C++不是内存安全的语言,代码库中自然频频出现内存漏洞,大量的时间被耗费在修补漏洞上. 微软自去年开始寻找用以替代的编程语言来解决内存安全问题,寻找终有所得--微软开始尝试使用Rust,并在一些情境下将其集成进代码库中.Rust是一种相对较新的编程语言,具有与C和C++相同的底层性能,并具备现代编程语言应有的功能集. 微软认为Rust颇具潜力,本文就将介绍微软将其用

  • Rust 能够取代 C 语言吗

    Rust 是 Mozilla 基金会的一个雄心勃勃的项目,号称是 C 语言和 C++ 的继任者.一直以来,C/C++ 中的一些基本问题都没能得到解决,比如分段错误.手动内存管理.内存泄漏风险和不可预测的编译器行为.Rust 的诞生就是为了解决这些问题,并提高安全性和性能. Evrone(一家软件公司)在很多项目中使用了 Rust,我们的工程师们这方面在积累了丰富的经验.在这篇文章中,我们将分享 Rust 的一些主要特性. 主要特性 强静态类型:无垃圾回收以及通过指针手动控制数据存储位置的能力:强

  • C和Java没那么香了,Serverless时代Rust即将称王?

    目录 高并发模式初探 C语言的高并发案例 Java的高并发实现 Go的高并发实现 Rust的高并发实现 总结 高并发模式初探 在这个高并发时代最重要的设计模式无疑是生产者.消费者模式,比如著名的消息队列kafka其实就是一个生产者消费者模式的典型实现.其实生产者消费者问题,也就是有限缓冲问题,可以用以下场景进行简要描述,生产者生成一定量的产品放到库房,并不断重复此过程:与此同时,消费者也在缓冲区消耗这些数据,但由于库房大小有限,所以生产者和消费者之间步调协调,生产者不会在库房满的情况放入端口,消

  • Rust 函数详解

    目录 函数参数 函数返回值 高阶函数 函数指针类型 函数作为参数 函数作为返回值 相关资料 Rust 支持多种编程范式,但更偏向于函数式,函数在 Rust 中是"一等公民",函数可以作为数据在程序中进行传递.跟 C.C++ 一样, Rust 也有一个唯一的程序入口 main 函数. 示例:程序入口 main 函数 fn main() { println!("Hello, world!"); } Rust 使用 fn 关键字来声明和定义函数,使用 snake case

  • js正则表达式常用函数详解(续)

    正则表达式对象的方法 1.test,返回一个 Boolean 值,它指出在被查找的字符串中是否存在模式.如果存在则返回 true,否则就返回 false. 2.exec,用正则表达式模式在字符串中运行查找,并返回包含该查找结果的一个数组. 3.compile,把正则表达式编译为内部格式,从而执行得更快. 正则表达式对象的属性 1.source,返回正则表达式模式的文本的复本.只读. 2.lastIndex,返回字符位置,它是被查找字符串中下一次成功匹配的开始位置. 3.input ($_),返回

  • Java 回调函数详解及使用

    Java 回调函数详解 前言: C语言中回调函数解释: 回调函数(Callback Function)是怎样一种函数呢? 函数是用来被调用的,我们调用函数的方法有两种: 直接调用:在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行.这里,A称为"主叫函数"(Caller),B称为"被叫函数"(Callee). 间接调用:在函数A的函数体里并不出现函数B的函数名,而是使用指向函数B的函数指针p来使内存中属于函数B的代码片断得以执行--听

  • Python实现屏幕截图的代码及函数详解

    废话不多说,先给大家看下python实现屏幕截图的代码,具体代码如下所述: from selenium import webdriver import time def capture(url, save_fn="capture.png"): browser = webdriver.Firefox() # Get local session of firefox browser.set_window_size(1200, 900) browser.get(url) # Load pag

  • SQL Server COALESCE函数详解及实例

    SQL Server COALESCE函数详解 很多人知道ISNULL函数,但是很少人知道Coalesce函数,人们会无意中使用到Coalesce函数,并且发现它比ISNULL更加强大,其实到目前为止,这个函数的确非常有用,本文主要讲解其中的一些基本使用:  首先看看联机丛书的简要定义: 返回其参数中第一个非空表达式语法: COALESCE ( expression [ ,...n ] ) 如果所有参数均为 NULL,则 COALESCE 返回 NULL.至少应有一个 Null 值为 NULL

  • Vue渲染函数详解

    前面的话 Vue 推荐在绝大多数情况下使用 template 来创建HTML.然而在一些场景中,真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器.本文将详细介绍Vue渲染函数 引入 下面是一个例子,如果要实现类似下面的效果.其中,H标签可替换 <h1> <a name="hello-world" href="#hello-world" rel="external nofol

  • javascript中Array()数组函数详解

    在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. Array()是一个用来构建数组的内建构造器函数.数组主要由如下三种创建方式: array = new Array() array =

  • COM组件中调用JavaScript函数详解及实例

    COM组件中调用JavaScript函数详解及实例 要求是很简单的,即有COM组件A在IE中运行,使用JavaScript(JS)调用A的方法longCalc(),该方法是一个耗时的操作,要求通知IE当前的进度.这就要求使用回调函数,设其名称为scriptCallbackFunc.实现这个技术很简单: 1 .组件方(C++) 组件A 的方法在IDL中定义: [id(2)] HRESULT longCalc([in] DOUBLE v1, [in] DOUBLE v2, [in, optional

  • thinkphp 字母函数详解T/I/N/D/M/A/R/U

    1. /** * 获取模版文件 格式 资源://模块@主题/控制器/操作 * @param string $template 模版资源地址 * @param string $layer 视图层(目录)名称 * @return string */T($template='',$layer='') 2. /** * 获取输入参数 支持过滤和默认值 * 使用方法: * <code> * I('id',0); 获取id参数 自动判断get或者post * I('post.name','','htmls

  • ThinkPHP函数详解之M方法和R方法

    首先给大家介绍ThinkPHP函数详解:M方法 M方法用于实例化一个基础模型类,和D方法的区别在于: 1.不需要自定义模型类,减少IO加载,性能较好: 2.实例化后只能调用基础模型类(默认是Model类)中的方法: 3.可以在实例化的时候指定表前缀.数据库和数据库的连接信息: D方法的强大则体现在你封装的自定义模型类有多强,不过随着新版ThinkPHP框架的基础模型类的功能越来越强大,M方法也比D方法越来越实用了. M方法的调用格式: M('[基础模型名:]模型名','数据表前缀','数据库连接

随机推荐