Rust - 函数

基础概念

  • 使用 fn 关键字声明函数,函数参数与返回值类型需要手动写好
    fn add_two(num: i32) -> i32 {
          
          
        num + 2
    }
    
  • 当函数最后一句表达式没有写分号时,则将其作为函数结果返回,也可以显式写出 return
    fn add_two(num: i32) -> i32 {
          
          
        num + 2
    }
    
    fn add_two(num: i32) -> i32 {
          
          
        return num + 2;
    }
    
  • 可以在函数当中声明函数,并能够在声明之前使用,但需要确保在有效的作用域范围当中,而非无限制
    fn main() {
          
          
        {
          
          
            // OK
            my_fn();
            fn my_fn(){
          
          
                //...
            }
            // OK
            my_fn();
        }
        // err
        my_fn();
    }
    
  • 不存在函数声明与函数表达式这一争论声音(相比 JS)

闭包

作为现代语言,Lambda(匿名函数)也是存在的,不过在 Rust 当中被称为 闭包(closure )

// 简写形式
let add_one = |num| num + 1;
// 完整
let add_one = |num: i32| -> i32 {
    
     
    num + 1 
};

作为函数参数使用:

fn main() {
    
    
    let num = 10;
    let arr = [1, 2, 3, 4, 5];
    let arr: Vec<i32> = arr.iter().map(|item| item * num).collect();
    // [10, 20, 30, 40, 50]
    println!("{:?}", arr);
}

这么一看,前端开发者就觉得怪了,这也能叫闭包?像是换了皮肤的箭头函数罢了,这需要做一个说明。

神奇的函数

虽然 Rust 与 JavaScript 一样,可以在函数当中声明函数,可该函数并不能读取函数作用域外的任何数据:

function main() {
    
    
    let num = 10;
    function log(){
    
    
        console.log(num);
    }
    // OK
    log();
}
fn main() {
    
    
    let num = 10;
    fn log() {
    
    
        // 错误,不存在 num
        println!("{}", num);
    }
    log();
}

想要读取外界数据时,需要将其切换为闭包形式:

fn main() {
    
    
    let num = 10;
    let log = || println!("{}", num);
    // OK
    log();
}

停顿一下,一函数不能读取当前作用域中的数据,其实就表明了,可以类似 JS 这么写,但是不能那么用,想使用数据,请显式传参。

要这么看,以后函数体内的函数声明,全使用闭包不就好了。并不行,虽然闭包可以读取外部数据,但不能自递归调用

该论点可参考论坛中的讨论:

Rust 的闭包能不能递归?(Rust 语言中文社区)

Is it possible to make a recursive closure in Rust?(stackoverflow)

小结

虽然可以在函数体内声明一个函数,但不可读取外界数据,不过这并不影响递归,如传统语言一般,将数据作为函数参数显示传入即可。

对此,想使用递归时,最好在函数体之外编写递归函数,因为写在执行代码当中的普通函数并没有什么优势,分离后还能条理清晰些。

而 JS 函数体内的函数,优势便在于减少不必要的传参

而闭包虽然可以读取数据,但是并不能自调用形成递归,更多时候是作为函数参数(Lambda 的主场)使用。

由此对比之下,像 JS 这种可随意拿取作用域当中任意数据的语言也是怪的离谱。

猜你喜欢

转载自blog.csdn.net/qq_49661519/article/details/123130758