额,Rust

首先,我觉得利益和技术需求远不足以撑起Rust社区,那剩下就是情怀了~

近几年新语言的官方定位和实际应用普遍有偏差。Rust是个例外,剑指C++,意在打造一个没有历史包袱的Modern语言。(我觉得阻碍Scala发展的其中一个原因也是迎合Java)。经历了大大小小的版本变革,Rust基本稳定了,并且社区反馈不错。学了点简单内容,记录一下。

管理工具

官方钦定了cargo

cargo new <ProjectName> --bin
cargo check
cargo build
cargo run

不加–bin默认编译出库。编译运行不加–release默认是debug版本。默认会创建git配置可以说非常方便。

速览

首先,变量默认immutable(包括引用形参)。回想C++中洪水般的const,这简直是行善积德。同时rust也提供了真const关键字,指的就是常量。

let后加mut表示mutable。Rust默认类型推导,也可以显示写明。类型后置应该是近期的审美趋势…

let i : i32 = 1;
let mut i = 3;
let str = String::new();

变量生命定义基本就这几种玩法。有了历史教训,程序默认使用类似工厂的方式创建对象。变量赋值默认移动语义,并且编译器会做安全检查。值得注意的是Rust对数字,布尔值,字面字符串是拷贝语义,这和C++的行为大致相同。

let i1 = 1;
let i2 = i1;
println("{}", i1); //pass

let str = "hah"
let str2 = str;
println("{}", str); //pass

let sstr = String::new();
let sstr2 = sstr;
println("{}", sstr); //error

被move过的变量不能再访问,编译器直接报错。上面使用了一个大写String类,和字符串字面值string是不同的,显然因为它是个类。

基础类型也可以 调方法。

let num = 100f64;
println!("{}", num.sqrt());

看类型定义。相对于class我更中意struct,注意结尾不需要分号。

struct Point {
  x : i32,
  y : i32,
  msg : String,
}
//
let p = Point {
  x : 10,
  y : 10,
  msg : String::from("start"),
};

是不是非常像JavaScript…而且还真有像ES7的展开语法…

let p2 = {
  ..p
};

成员方法使用impl在别处定义,而且可以分割成多个impl块。

impl Point {
  fn module(&self) -> f64{
    ((self.x * self.x + self.y * self.y) as f64).sqrt()
  }
}

数据与行为分离,同时又不失封装。设计虽小,但令人眼前一亮。

接着函数的声明方式。

fn foo(i : i32) {}
fn foo2() -> i32 {}
fn foo3(str : &String) {}
fn foo4(str : &mut String) {}
//
let mut str = String::new();
foo3(&str);
foo4(&mut str);
  • 函数声明的形式基本上就这几种。有几点和传统语言不同
    1. 默认move实参
    2. 默认引用immutable
    3. 显示使用mut形参

此外函数调用可以显式传引用

*Pattern Match

rust的模式匹配略感怪异。你不能使用i32去匹配一个Option<i32>,这和我原本的认知不同。

首先,这里的enum我觉得其实混入了union的语义,也就是variant。

enum Number{ONE, TWO, THREE,}
enum Norm{
  Point{x:i32, y:i32,},
  Size(i32),
}
//
let norm = Norm::Size(10);
match norm {
  Norm::Size(size) => println!("get {}", size),
  Norm::Point{x,y} => println!("get {}, {}", x, y),
  _=>(),
}

match会逐一检查enum的variant,缺省情况需要用_占位,否则编译报错。

看下Option的定义

enum Option<T>
    None,
    Some(T),
}

Some是Option的子类。也就是说这个形式会递归下去,也就是说Rust的函数都返回Option,而且从一开始设计库就考虑了空值的问题。这点C++,Java很难做到,除非大洗牌。

*泛型

上面的Option<T>出现了模板似的的尖括号。我事先以为Rust就是照搬了C++的模板,实际上它的语法更像Java。

fn largest(list: &[T]) -> T {
    let mut largest = list[0];
 
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
 
    largest
}
struct Point {
    x: T,
    y: T,
}
//
let p = Point{x: 1, y: 2};

泛型对象声明看起来像C++17。

trait

trait用起来就像Java的interface。区别就是trait在编译时确定调用的函数。其实就类似Go的interface…

pub trait Print {
  fn print(&self);
}
pub struct PrinterA {}
impl Print for PrinterA {
  fn print(&self) {}
}

我个人认为trait比interface表达的语义好一点。比如上面不用写成Printable或IPrint。

rust最基本的内容就这些了。有缘再深入了解一下。

Leave a Reply

Your email address will not be published. Required fields are marked *