新手学做网站要多久,怎么可以找到做公益的网站,阿里云域名查询和注册,北京市住房及城乡建设部网站闭包 迭代器
闭包#xff08;Closure#xff09;通常是指词法闭包#xff0c;是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量#xff0c;在函数式编程范式中也被称为自由变量#xff0c;是指并不是在闭包内定义的变量。将自…闭包 迭代器
闭包Closure通常是指词法闭包是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量在函数式编程范式中也被称为自由变量是指并不是在闭包内定义的变量。将自由变量和自身绑定的函数就是闭包。 闭包的两大特性
延迟执行。返回的闭包只有在需要调用的时候才会执行。捕获环境变量。闭包会获取其定义时所在作用域中的自由变量以供之后调用时使用。
Rust的闭包语法形式参考了Ruby语言的lambda表达式:
fn main(){let add_op |a:i32,b:i32| - i32 {ab};let c add_op(1,2);println!(12{},c);
}闭包的语法都大差不差rustrubypython等都差不多一个样 rust闭包的具体实现方式可以看Rust编程之道里面有讲解目前没用到闭包这里就不做讲解了看了不用也记不住。
智能指针
智能指针Box, Rc, Arc, Cell, RefCell, Cow等等对原始指针进行包装并添加额外的语义。 Box 是最直接的智能指针——它将数据分配到堆上而非栈上在栈上只留一个指向堆中数据的指针。Box 没有性能开销在下面的情况下使用
递归类型如链表和树必须使用Box去包装引用自身的字段以保证编译时能确定大小数据太大希望移动所有权时减少拷贝数据消耗希望持有特定 trait 的值无关它的实际类型即不知晓它的大小 作者_YKI https://www.bilibili.com/read/cv31741541/ 出处bilibili
Rc提供在堆中分配的 T 类型值的共享所有权。在 Rc 上调用克隆方法会生成一个指向堆中相同地址的新指针。当指向给定地址的最后一个 Rc 指针被销毁时存储在该地址中的值也会被删除。
IO
Rust官方对于IO实现了IO trait大部分函数看名字就知道作用
pub trait Read {// Required methodfn read(mut self, buf: mut [u8]) - Resultusize;// Provided methodsfn read_vectored(mut self, bufs: mut [IoSliceMut_]) - Resultusize { ... }//is_read_vectored目前还是nightly APIfn is_read_vectored(self) - bool { ... }fn read_to_end(mut self, buf: mut Vecu8) - Resultusize { ... }fn read_to_string(mut self, buf: mut String) - Resultusize { ... }fn read_exact(mut self, buf: mut [u8]) - Result() { ... }fn read_buf(mut self, buf: BorrowedCursor_) - Result() { ... }fn read_buf_exact(mut self, cursor: BorrowedCursor_) - Result() { ... }fn by_ref(mut self) - mut Selfwhere Self: Sized { ... }fn bytes(self) - BytesSelf //是指将 Read 按逐字节的方式转换成迭代器。迭代器为Resultu8这个Result也是std::io::ResultTwhere Self: Sized { ... }fn chainR: Read(self, next: R) - ChainSelf, R where Self: Sized { ... }fn take(self, limit: u64) - TakeSelf where Self: Sized { ... }
}
pub trait Write {// Required methodsfn write(mut self, buf: [u8]) - Resultusize;fn flush(mut self) - Result();// Provided methodsfn write_vectored(mut self, bufs: [IoSlice_]) - Resultusize { ... }fn is_write_vectored(self) - bool { ... }fn write_all(mut self, buf: [u8]) - Result() { ... }fn write_all_vectored(mut self, bufs: mut [IoSlice_]) - Result() { ... }fn write_fmt(mut self, fmt: Arguments_) - Result() { ... }fn by_ref(mut self) - mut Selfwhere Self: Sized { ... }
}很多类型实现了标准 IO 特型File、TcpStream、Vec、[u8]注意返回类型是std::io::Result不是std::Result
pub type ResultT ResultT, Error;使用IO的demo
use std::io::prelude::*;
use std::fs::File;fn main() - std::io::Result() {let data bsome bytes;let mut pos 0;let mut buffer File::create(foo.txt)?;while pos data.len() {let bytes_written buffer.write(data[pos..])?;pos bytes_written;}Ok(())
}安全并发
Rust中的线程管理和线程同步工具相关库为stdthread模块和stdsync模块。Rust中的线程是本地线程每个线程都有自己的栈和本地状态。创建一个线程如下
use std::thread;
fn main(){let mut v vec![]for id in 0..5 {let child thread::spawn(move || {println!(in child:{},id);});//spawn是Rust中线程初始化的函数//直接使用threadspawn生成的线程默认没有名称并且其栈大小默认为2MB。//这里使用move关键字来强行将捕获变量id的所有权转移到闭包中。v.push(child);}println!(in main join before:);for child in v {child.join(); //等待child结束后再接着运行//但是child之间并没有相互等待的关系输出是乱序的}println!(int main joint after);
}并发安全是Rust的一个卖点。Rust中内置了两个traitstd::marker::Send和std::marker::Sync实现了Send的类型可以安全地在线程间传递所有权即跨线程移动实现了Sync的类型可以安全地在线程间传递不可变借用即跨线程共享。和Send/Sync相反的标记是Send/Sync表示不能在线程间安全传递的类型。智能指针Rc实现了Send/Sync因为Rc内部并不是原子操作在线程间传递会导致技术不准确。Rust提供了线程安全版的Rc即Arc内部使用的是原子操作可以在线程间安全传递。 这两个标记trait反映了Rust看待线程安全的哲学多线程共享内存并非线程不安全问题所在问题在于错误地共享数据。通过Send和Sync将类型贴上“标签”由编译器来识别这些类型是否可以在多个线程之间移动或共享从而做到在编译期就能发现线程不安全的问题。 《Rust编程之道》 至于为什么这两个trait就可以实现并发安全这两个具体怎么用Rust中的锁怎么写这部分等到后面用到再仔细分析目前没有写项目学了也是纸上谈兵。
宏系统
在 Rust 中宏分为两大类声明式宏( declarative macros ) macro_rules! 和三种过程宏( procedural macros ):
#[derive]在之前多次见到的派生宏可以为目标结构体或枚举派生指定的代码例如 Debug 特征类属性宏(Attribute-like macro)用于为目标添加自定义的属性类函数宏(Function-like macro)看上去就像是函数调用 声明宏就是与传统的编程语言中的宏的概念是差不多的但过程宏是使用源代码作为输入参数基于代码进行一系列操作后再输出一段全新的代码。有点类似于Python中的装饰器一样。 macro_rules!用来声明一个声明宏也可以叫生成规则宏他可以定义代码生成规则声明式宏允许我们写出类似 match 的代码。match 表达式是一个控制结构其接收一个表达式然后将表达式的结果与多个模式进行匹配一旦匹配了某个模式则该模式相关联的代码将被执行。语法格式
macro_rules! macro_name{() { //跟match的语法非常像code;};
}案例
#[macro_export] //注释将宏进行了导出这样其它的包就可以将该宏引入到当前作用域中然后才能使用。
macro_rules! vec {($($x:expr),*) ( { //这里的匹配规则有点像正则表达式一样$x:expr表示可以匹配任何类型*表示可以重复无数次let mut temp_vec Vec::new();$(temp_vec.push($x);)*temp_vec} );
}大部分人都是宏的使用者很少编写啥时候用到再学吧。
总结
Rust语言的卖点就是安全安全还是安全。这个安全包括内存安全并发安全。其实这两点Python都能做到但是为什么还要推出Rust呢性能是关键 Python保证内存安全是使用GC垃圾回收机制保证并发安全是使用GIL锁。这两个机制都会极大降低Python的运行速度【目前据说GIL锁在新版本的Python中已经可以移除了但是Python的速度还是没法跟Rust比】。 Rust确保这两点安全的方法是所有权、声明周期机制以及强大的类型系统。所有权系统和生命周期确保了一份数据在同一时刻只会被一个变量所拥有有效避免了悬垂指针以及双重释放等内存问题。内存安全的Bug和并发安全的Bug产生的内在原因是相同的都是因为内存的不正当访问而造成的。同样利用装载了所有权的强大类型系统Rust还解决了并发安全的问题。Rust编译器会通过静态检查分析在编译期就检查出多线程并发代码中所有的数据竞争问题。 类型系统是指编程语言中对于类型的一套规则并不是真的有个系统类型系统的主要作用就是类型推导类型检测类型转换Rust是类型安全的即在运行时不会出现类型错误。 Rust作为后起之秀借鉴了很多语言的设计思想HaskellC/CPythonRuby等等像智能指针模板特化等很多新的技术都有借鉴这些也一定程度上确保了内存安全。
谈完Rust设计哲学再谈一谈Rust的编程范式不用说基本上所有现代语言都是混合编程范式的理论上Rust可以支持各种编程范式但是哪种支持更完备编程更方便自然是不一样的。在Rust中不管哪一种单一编程范式来进行编程都很难受面向对象函数式泛型编程都是这样的。对于面向对象Rust中有struct、方法和trait来实现面向对象。对于函数式Rust中有闭包以及一切皆类型的类型系统。对于泛型编程Rust有泛型有模板特化const模板参数等支持。所以对于Rust项目比较推荐的编程范式是轻度面向对象泛型编程函数式编程做为边边角角的辅助使用。更多可以看一下这篇文章 至此Rust编程就已经完结了泛型编程和宏系统的应用Rust设计模式的实现异步编程和数据并行编程unsafe特性与其他语言相互调用等等等等这些特性我建议用到再学因为学完不用很快就忘了没必要有一些概念不清楚的不要去百度去看Rust圣经或者直接去看Rust标准库官方文档写的非常明确。 下一步就是开始从0写操作系统清华的操作系统训练营还有好几天才开营先学起来下一篇打算跟着Rust实战这本书写一个CPU模拟器。