发布于 2026-01-06 0 阅读
0

Rust 函数式编程 DEV 全球展示挑战赛,由 Mux 呈现:展示你的项目!

Rust 中的函数式编程

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

一个月前,当我第一次使用ReasonML开发一个非商业项目时,我获得了一种全新的体验——函数式编程。这门语言是OCaml的另一种语法。OCaml 本身就是一种纯函数式语言,它提供的特性非常有趣。例如:类型推断、强类型系统、代数数据类型等等。是不是很有意思?

尝试之后,我对函数式编程产生了兴趣。最终,我尝试用另一种语言——Rust——来实现函数式编程范式。

介绍

函数式编程(FP)是一种编程范式,它允许我们编写富有表现力、简洁且优雅的代码。函数式编程还有助于开发者管理代码,避免重复编写相同的代码(DRY原则)。其他函数式语言包括Lisp、Clojure、Erlang、Haskell、R等等。

好吧,但是为什么是 Rust 呢?

问题是,Rust 是函数式语言吗?答案是否定的。虽然 Rust 本身受到了ML 系列语言的启发,但它并非函数式语言。不过幸运的是,Rust 拥有一些与其他函数式语言类似的特性,例如:代数数据类型、表达力强的类型等等。

目录

基本类型

为了避免贸然上手,我们最好先了解Rust中的几种数据类型。这一点也适用于所有编程语言。

布尔值

最基本的数据类型是简单true / false值,在 Rust 中称为bool

let x = true;
let y: bool = false;
Enter fullscreen mode Exit fullscreen mode

查尔

char数据类型只有一个 Unicode 值。我们可以使用char带单个反斜杠 ( ') 的数据类型。

let x = 'x';
let two_hearts = '💕';
Enter fullscreen mode Exit fullscreen mode

与其他一些语言不同,charRust 中 不是一个字节,而是四个字节。

数字类型

Rust 有几种数值类型类别变体,例如 signed( i) 和 unsigned( u),固定大小(,,,8可变大小()类型。163264isizeusize

let x = 42; // `x` has type `i32`.
let y = 1.0; // `y` has type `f64`.
Enter fullscreen mode Exit fullscreen mode

数组

像许多其他编程语言一样,Rust 也具有数组数据类型。默认情况下,Rust 中的数组无法更改,除非你使用 `new` 初始化它。mut

let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // m: [i32; 3]
Enter fullscreen mode Exit fullscreen mode

函数

函数也有数据类型!例如:

fn foo(x: i32) -> i32 { x }
let x: fn(i32) -> i32 = foo;
Enter fullscreen mode Exit fullscreen mode

在这种情况下,该foo ()函数具有返回类型numeric: i32,并返回该值x

更多信息,请查看这里:原始类型

关闭

闭包是一种机制,它允许内部函数在外部函数返回后,仍然能够访问外部函数词法作用域中定义的变量。理解到这里了吗?简而言之,闭包就是一个内部函数,它能够访问作用域内(包括内部和外部)的值。

fn fmt(prev_str: &str) -> String {
    let mut new_str = String::new();

    let closure_annotated = |next_str| -> String {
        new_str.push_str(prev_str);
        new_str.push_str(next_str);
        return new_str;
    };

    closure_annotated("dolor sit amet")
}

let r_txt = "Lorem ipsum ";
assert_eq!("Lorem ipsum dolor sit amet", fmt(r_txt));
Enter fullscreen mode Exit fullscreen mode

在这种情况下,在访问变量并更改其值的new_str.push_str ()部分。closure_annotatednew_str

咖喱

柯里化是函数式编程中的一种过程,它允许我们将一个带有多个参数的函数转换为一系列嵌套函数。柯里化会返回一个新函数,该函数期望下一个参数以内联方式传入。

#[derive(Debug)]
struct States<'a> {
    a: &'a i32,
    b: &'a i32,
}

trait Currying {
    type ReturnType: Fn(i32) -> i32;
    fn add(self) -> Self::ReturnType;
}

impl Currying for States<'static>{
    type ReturnType = Box<dyn Fn(i32) -> i32>;

    fn add(self) -> Self::ReturnType {
        Box::new(move|x| {
            x * self.a
        })
    }
}

let r_value: States = States {
    a: &100,
    b: &100
};

let r1 = r_value.add();
let r2 = r1(5);

assert_eq!(500, r2);

Enter fullscreen mode Exit fullscreen mode

这里有两个参数,每个参数都有一个数值数据类型;然后,` asection`部分是一个函数接口,用于初始化函数。这些特性类似于TypeScript 接口btrait

高阶函数(HOF)

高阶函数是指使用其他函数作为参数或返回值的函数。

fn map<F>(arr: &[i32], func: F) -> Vec<i32> where F: Fn(&i32) -> i32{
    let mut new_array: Vec<i32> = vec![];
    for i in arr.iter() {
        new_array.push(func(i))
    }

    return new_array
}

let lists = vec![1, 4, 9, 16];
let result = map(&lists, |i| *i + 2);

assert_eq!(vec![3, 6, 11, 18], result)
Enter fullscreen mode Exit fullscreen mode

所以,` funcand`map是高阶函数,其中此函数用于更改数组中的每个元素。返回结果是一个与修改后的数组长度相同的新数组originalArray

懒惰评估

惰性求值或非严格求值是指在expression/function需要某个值时才对其进行求值。其目的是避免重复求值。

struct State {
    x: i32,
}

trait Lazy {
    fn add(&self) -> i32;
    fn multiply(&self) -> i32;
    fn add_or_multiply(&self, add: bool) -> i32;
}

impl Lazy for State {
    fn add(&self) -> i32 {
        println!("executing add");
        &self.x + &self.x
    }

    fn multiply(&self) -> i32 {
        println!("executing multiply");
        &self.x * &self.x
    }

    fn add_or_multiply(&self, add: bool) -> i32 { 
        match add {
            true => self.add(),
            false =>  self.multiply(),
        }
    }
}

let val: State = State {
    x: 20
};

assert_eq!(40, val.add_or_multiply(true));
assert_eq!(400, val.add_or_multiply(false));
Enter fullscreen mode Exit fullscreen mode

函数式编程(FP)具有诸多优势,因此越来越受欢迎。然而,每种编程范式都有其独特的术语,函数式编程也不例外。我希望通过提供这份术语表,让学习函数式编程变得更加轻松✌️

源代码:rustfp.github

文章来源:https://dev.to/natserrat/function-programming-in-rust-3im8