From de952b235848af427fe0417b2977622a44f939a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Sat, 7 Mar 2020 11:03:37 +0800 Subject: [PATCH] add rust function closures --- rust-examples/src/closures.rs | 232 +++++++++++++++++++++++++++++++++ rust-examples/src/functions.rs | 110 ++++++++++++++++ rust-examples/src/main.rs | 6 + 3 files changed, 348 insertions(+) create mode 100644 rust-examples/src/closures.rs create mode 100644 rust-examples/src/functions.rs diff --git a/rust-examples/src/closures.rs b/rust-examples/src/closures.rs new file mode 100644 index 00000000..39330968 --- /dev/null +++ b/rust-examples/src/closures.rs @@ -0,0 +1,232 @@ +///闭包 +//by reference: &T 默认 +//by mutable reference: &mut T +//by value: T +pub fn closures() { + //闭包是lambda,一个表达式可以省略大括号 + fn function(i: i32) -> i32 { i + 1 } + let closure_annotated = |i: i32| -> i32 { i + 1 }; + let closure_inferred = |i| i + 1; + let i = 1; + println!("function: {}", function(i)); + println!("closure_annotated: {}", closure_annotated(i)); + println!("closure_inferred: {}", closure_inferred(i)); + let one = || 1; + println!("closure returning one: {}", one()); + capturing(); + let haystack = vec![1, 2, 3]; + let contains = move |needle| haystack.contains(needle); + println!("{}", contains(&1)); + println!("{}", contains(&4)); + //println!("There're {} elements in vec", haystack.len()); + + input_parameters(); + type_anonymity(); + input_functions(); + output_parameters(); + closures_std(); + higher_order_functions(); + diverging_functions(); +} + +fn capturing() { + use std::mem; + let color = "green"; + let print = || println!("`color`: {}", color); + print(); + + let _reborrow = &color;//闭包使用的color能被继续借用 + print();//直到最后一次使用print + + let _color_moved = color;//最后使用`print`后允许移动或重新借用 + let mut count = 0; + let mut inc = || { + count += 1; + println!("`count`: {}", count); + }; + inc(); + //let _reborrow = &count;//已经被作为可变的借用出去,不可再借用给不可变的 + inc(); + let _count_reborrowed = &mut count; + //非copy的,被移动进闭包 + let movable = Box::new(3); + let consume = || { + println!("`movable`: {:?}", movable); + mem::drop(movable); + }; + + consume();//仅能被使用一次。 +} + +fn input_parameters() { + //以闭包作为参数并调用它的函数。 + fn apply(f: F) where + // The closure takes no input and returns nothing. + F: FnOnce() {//按值捕获 + // ^ TODO: Try changing this to `Fn` or `FnMut`. + f(); + } + + // A function which takes a closure and returns an `i32`. + fn apply_to_3(f: F) -> i32 where F: Fn(i32) -> i32 { + f(3) + } + + use std::mem; + + let greeting = "hello"; + //从借来的引用创建自己拥有的数据 + let mut farewell = "goodbye".to_owned(); + let diary = || { + println!("I said {}.", greeting);//捕获引用 + farewell.push_str("!!!");//捕获可变引用 + println!("Then I screamed {}.", farewell); + println!("Now I can sleep. zzzzz"); + mem::drop(farewell);//捕获值 + }; + apply(diary); + let double = |x| 2 * x; + println!("3 doubled: {}", apply_to_3(double)); +} + +fn type_anonymity() { + // `F`必须是泛型的 + fn apply(f: F) where + F: FnOnce() { + f(); + } +} + +fn input_functions() { + //无返回值的 + fn call_me(f: F) { + f(); + } + + fn function() { + println!("I'm a function!"); + } + + //满足Fn的闭包 + let closure = || println!("I'm a closure!"); + + call_me(closure); + call_me(function); +} + +fn output_parameters() { + fn create_fn() -> impl Fn() { + //必须使用move关键字,强制按值捕获避免函数退出时通过引用捕获的被丢弃而留下无效引用 + let text = "Fn".to_owned(); + move || println!("This is a: {}", text) + } + + fn create_fnmut() -> impl FnMut() { + let text = "FnMut".to_owned(); + move || println!("This is a: {}", text) + } + + fn create_fnonce() -> impl FnOnce() { + let text = "FnOnce".to_owned(); + move || println!("This is a: {}", text) + } + + let fn_plain = create_fn(); + let mut fn_mut = create_fnmut(); + let fn_once = create_fnonce(); + + fn_plain(); + fn_mut(); + fn_once(); +} + +///https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find +fn closures_std() { + //any + let vec1 = vec![1, 2, 3]; + let vec2 = vec![4, 5, 6]; + println!("2 in vec1: {}", vec1.iter().any(|&x| x == 2));//不消耗集合,使用引用捕获 + println!("2 in vec2: {}", vec2.into_iter().any(|x| x == 2));//消耗集合,使用值捕获 + let array1 = [1, 2, 3]; + let array2 = [4, 5, 6]; + println!("2 in array1: {}", array1.iter().any(|&x| x == 2)); + println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2)); + + //find + let vec1 = vec![1, 2, 3]; + let vec2 = vec![4, 5, 6]; + let mut iter = vec1.iter();//&i32 + let mut into_iter = vec2.into_iter();//i32 + println!("Find 2 in vec1: {:?}", iter.find(|&&x| x == 2));//`&&i32` to `i32` + println!("Find 2 in vec2: {:?}", into_iter.find(|&x| x == 2));//`&i32` to `i32` + let array1 = [1, 2, 3]; + let array2 = [4, 5, 6]; + println!("Find 2 in array1: {:?}", array1.iter().find(|&&x| x == 2)); + println!("Find 2 in array2: {:?}", array2.into_iter().find(|&&x| x == 2)); + + //position index + let vec = vec![1, 9, 3, 3, 13, 2]; + let index_of_first_even_number = vec.iter().position(|x| x % 2 == 0); + assert_eq!(index_of_first_even_number, Some(5)); + let index_of_first_negative_number = vec.iter().position(|x| x < &0); + assert_eq!(index_of_first_negative_number, None); + //into_iter这个只能放最后,会消耗集合,会从左到右移动每个元素,之后集合不可用 + let index_of_first_even_number = vec.into_iter().position(|x| x % 2 == 0); + assert_eq!(index_of_first_even_number, Some(5)); +} + +fn higher_order_functions() { + fn is_odd(n: u32) -> bool { + n % 2 == 1 + } + + println!("Find the sum of all the squared odd numbers under 1000"); + let upper = 1000; + let mut acc = 0; + for n in 0.. {//无穷大 + let n_squared = n * n; + if n_squared >= upper { + break; + } else if is_odd(n_squared) { + acc += n_squared; + } + } + println!("imperative style: {}", acc); + //函数式风格 + let sum_of_squared_odd_numbers: u32 = + (0..).map(|n| n * n) + .take_while(|&n_squared| n_squared < upper) + .filter(|&n_squared| is_odd(n_squared)) // That are odd + .fold(0, |acc, n_squared| acc + n_squared); // Sum them + println!("functional style: {}", sum_of_squared_odd_numbers); +} + +fn diverging_functions() { + fn foo() -> ! { + panic!("This call never returns."); + } + + //尽管返回值中没有信息,但该函数照常返回。 + fn some_fn() { + () + } + let a: () = some_fn(); + println!("This function returns and you can see this line."); + //该函数永远不会将控制流返回给调用者。直接抛出恐慌 + //let x= panic!("This call never returns."); + println!("You will never see this line!"); + fn sum_odd_numbers(up_to: u32) -> u32 { + let mut acc = 0; + for i in 0..up_to { + let addition: u32 = match i % 2 == 1 { + true => i, + false => continue,//不返还,不违反match + }; + acc += addition; + } + acc + } + println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9)); + + //println!("{}", foo()) //error This call never returns. +} \ No newline at end of file diff --git a/rust-examples/src/functions.rs b/rust-examples/src/functions.rs new file mode 100644 index 00000000..a5b41b5a --- /dev/null +++ b/rust-examples/src/functions.rs @@ -0,0 +1,110 @@ +///函数 +pub fn functions() { + fizzbuzz(1); + fizzbuzz_to(1); + methods(); +} + +fn is_divisible_by(lhs: u32, rhs: u32) -> bool { + //提前返回 + if rhs == 0 { + return false; + } + + //最后的return 不是必须的 + lhs % rhs == 0 +} + +//没有返回值: () +fn fizzbuzz(n: u32) -> () { + if is_divisible_by(n, 15) { + println!("fizzbuzz"); + } else if is_divisible_by(n, 3) { + println!("fizz"); + } else if is_divisible_by(n, 5) { + println!("buzz"); + } else { + println!("{}", n); + } +} + +//反回: () 可以省略 +fn fizzbuzz_to(n: u32) { + for n in 1..n + 1 { + fizzbuzz(n); + } +} + +//方法是附加给对象的函数,这些方法可以通过self关键字访问对象及其其他方法的数据 +fn methods() { + struct Point { + x: f64, + y: f64, + } + + impl Point { + //对象的静态方法 + fn origin() -> Point { + Point { x: 0.0, y: 0.0 } + } + + fn new(x: f64, y: f64) -> Point { + Point { x, y } + } + } + + struct Rectangle { + p1: Point, + p2: Point, + } + + impl Rectangle { + fn area(&self) -> f64 { + let Point { x: x1, y: y1 } = self.p1; + let Point { x: x2, y: y2 } = self.p2; + ((x1 - x2) * (y1 - y2)).abs() + } + + //对象的方法 + fn perimeter(&self) -> f64 { + let Point { x: x1, y: y1 } = self.p1; + let Point { x: x2, y: y2 } = self.p2; + 2.0 * ((x1 - x2).abs() + (y1 - y2).abs()) + } + + fn translate(&mut self, x: f64, y: f64) { + self.p1.x += x; + self.p2.x += x; + + self.p1.y += y; + self.p2.y += y; + } + } + struct Pair(Box, Box); + + impl Pair { + fn destroy(self) { + let Pair(first, second) = self; + println!("Destroying Pair({}, {})", first, second); + } + } + + let rectangle = Rectangle { + //静态方法使用双冒号 + p1: Point::origin(), + p2: Point::new(3.0, 4.0), + }; + println!("Rectangle perimeter: {}", rectangle.perimeter()); + println!("Rectangle area: {}", rectangle.area()); + + let mut square = Rectangle { + p1: Point::origin(), + p2: Point::new(1.0, 1.0), + }; + square.translate(1.0, 1.0); + + let pair = Pair(Box::new(1), Box::new(2)); + + pair.destroy(); +} + diff --git a/rust-examples/src/main.rs b/rust-examples/src/main.rs index 4da02a13..6d2cf52b 100644 --- a/rust-examples/src/main.rs +++ b/rust-examples/src/main.rs @@ -1,16 +1,20 @@ use std::fmt; use std::fmt::{Display, Error, Formatter}; +use crate::closures::*; use crate::conversion::*; use crate::custom_types::*; use crate::flow_control::*; use crate::formatted_print::*; +use crate::functions::*; use crate::primitives::*; use crate::types::*; use crate::variable_bindings::*; pub mod formatted_print; +pub mod functions; pub mod flow_control; +pub mod closures; pub mod conversion; pub mod types; pub mod primitives; @@ -25,4 +29,6 @@ fn main() { types(); conversion(); flow_control(); + functions(); + closures(); } -- GitLab