午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

?半小時(shí)入門(mén)Rust,這是一篇Rust代碼風(fēng)暴

 貓熊飛飛 2020-03-18

機(jī)器之心報(bào)道

參與:思、Jamin

據(jù)說(shuō)很多開(kāi)發(fā)者一天入門(mén) Python,兩天上手 Go,但到了 Rust 就會(huì)發(fā)現(xiàn)畫(huà)風(fēng)隱約有些不對(duì)。它從語(yǔ)法到特性,似乎都要復(fù)雜一些。本文介紹的就是 Rust,作者表示,通過(guò)解析大量代碼,「半個(gè)小時(shí)」就能入門(mén) Rust。

?半小時(shí)入門(mén)Rust,這是一篇Rust代碼風(fēng)暴

Rust 是一門(mén)系統(tǒng)編程語(yǔ)言,專(zhuān)注于安全,尤其是并發(fā)安全。它支持函數(shù)式和命令式以及泛型等編程范式的多范式語(yǔ)言,且 TensorFlow 等深度學(xué)習(xí)框架也把它作為一個(gè)優(yōu)秀的前端語(yǔ)言。

Rust 在語(yǔ)法上和 C、C 類(lèi)似,都由花括弧限定代碼塊,并有相同的控制流關(guān)鍵字,但 Rust 設(shè)計(jì)者想要在保證性能的同時(shí)提供更好的內(nèi)存安全。Rust 自 2016 年就已經(jīng)開(kāi)源了,在各種開(kāi)發(fā)者調(diào)查中,它也總能獲得「最受歡迎的語(yǔ)言」這一稱(chēng)贊,目前該開(kāi)源項(xiàng)目已有 42.9K 的 Star 量。

機(jī)器之心的讀者大多數(shù)都非常熟悉 Python,而 Rust 就沒(méi)那么熟悉了。在 Amos 最近的一篇博文中,他表示如果閱讀他的作品,我們半個(gè)小時(shí)就能入門(mén) Rust。因此在這篇文章中,我們將介紹該博文的主要內(nèi)容,它并不關(guān)注于 1 個(gè)或幾個(gè)關(guān)鍵概念,相反它希望通過(guò)代碼塊縱覽 Rust 的各種特性,包括各種關(guān)鍵詞與符號(hào)的意義。

在 HackNews 上,很多開(kāi)發(fā)者表示這一份入門(mén)教程非常實(shí)用,Rust 的入門(mén)門(mén)檻本來(lái)就比較高,如果再介紹各種復(fù)雜的概念與特性,很容易出現(xiàn)「從入門(mén)到勸退」。因此這種從實(shí)例代碼出發(fā)的教程,非常有意義。

?半小時(shí)入門(mén)Rust,這是一篇Rust代碼風(fēng)暴

從變量說(shuō)起

let 能綁定變量:

let x; // declare 'x'x = 42; // assign 42 to 'x'let x = 42; // combined in one line

可以使用 :來(lái)制定變量的數(shù)據(jù)類(lèi)型,以及數(shù)據(jù)類(lèi)型注釋?zhuān)?/p>

let x: i32; // `i32` is a signed 32-bit integerx = 42;// there's i8, i16, i32, i64, i128//    also u8, u16, u32, u64, u128 for unsignedlet x: i32 = 42; // combined in one line

如果你聲明一個(gè)變量并在初始化之前就調(diào)用它,編譯器會(huì)報(bào)錯(cuò):

let x;foobar(x); // error: borrow of possibly-uninitialized variable: `x`x = 42;

然而,這樣做完全沒(méi)問(wèn)題:

let x;x = 42;foobar(x); // the type of `x` will be inferred from here

下劃線表示特殊的命名,或者更確切地說(shuō)是「缺失的命名」,它和 Python 的用法有點(diǎn)像:

// this does *nothing* because 42 is a constantlet _ = 42;// this calls `get_thing` but throws away its resultlet _ = get_thing();

以下劃線開(kāi)頭的命名是常規(guī)命名,只是編譯器不會(huì)警告它們未被使用:

// we may use `_x` eventually, but our code is a work-in-progress// and we just wanted to get rid of a compiler warning for now.let _x = 42;

相同命名的單獨(dú)綁定是可行的,第一次綁定的變量會(huì)取消:

let x = 13;let x = x 3;// using `x` after that line only refers to the second `x`,// the first `x` no longer exists.

Rust 有元組類(lèi)型,可以將其看作是「不同數(shù)據(jù)類(lèi)型值的定長(zhǎng)集合」。

let pair = ('a', 17);pair.0; // this is 'a'pair.1; // this is 17

如果真的想配置 pair 的數(shù)據(jù)類(lèi)型,可以這么寫(xiě):

let pair: (char, i32) = ('a', 17);

元組在賦值時(shí)可以被拆解,這意味著它們被分解成各個(gè)字段:

let (some_char, some_int) = ('a', 17);// now, `some_char` is 'a', and `some_int` is 17

當(dāng)一個(gè)函數(shù)返還一個(gè)元組時(shí)會(huì)非常有用:

let (left, right) = slice.split_at(middle);

當(dāng)然,在解構(gòu)一個(gè)元組時(shí),可以只分離它的一部分:

let (_, right) = slice.split_at(middle);

分號(hào)表示語(yǔ)句的結(jié)尾:

let x = 3;let y = 5;let z = y x;

不加分號(hào)意味著語(yǔ)句可以跨多行:

let x = vec![1, 2, 3, 4, 5, 6, 7, 8]    .iter()    .map(|x| x   3)    .fold(0, |x, y| x   y);

函數(shù)來(lái)了

fn 聲明一個(gè)函數(shù)。下面是一個(gè)空函數(shù):

fn greet() { println!('Hi there!');}

這是一個(gè)返還 32 位帶符號(hào)整數(shù)值的函數(shù)。箭頭表示返還類(lèi)型:

fn fair_dice_roll() -> i32 {    4}

花括號(hào)表示了一個(gè)代碼塊,且擁有其自己的作用域:

// This prints 'in', then 'out'fn main() { let x = 'out'; { // this is a different `x` let x = 'in'; println!(x); } println!(x);}

代碼塊也是表示式,表示其計(jì)算為一個(gè)值。

// this:let x = 42;// is equivalent to this:let x = { 42 };

在一個(gè)代碼塊中,可以有多個(gè)語(yǔ)句:

let x = { let y = 1; // first statement let z = 2; // second statement y z // this is the *tail* - what the whole block will evaluate to};

這也是為什么「省略函數(shù)末尾的分號(hào)」等同于加上了 Retrun,這些都是等價(jià)的:

fn fair_dice_roll() -> i32 {    return 4;}fn fair_dice_roll() -> i32 {    4}

if 條件語(yǔ)句也是表達(dá)式:

fn fair_dice_roll() -> i32 { if feeling_lucky { 6 } else { 4 }}

match 匹配器也是一個(gè)表達(dá)式:

fn fair_dice_roll() -> i32 {    match feeling_lucky {        true => 6,        false => 4,    }}

Dots 通常用于訪問(wèn)某個(gè)對(duì)象的字段:

let a = (10, 20);a.0; // this is 10let amos = get_some_struct();amos.nickname; // this is 'fasterthanlime'

或者調(diào)用對(duì)象的方法:

let nick = 'fasterthanlime';nick.len(); // this is 14

雙冒號(hào)與此類(lèi)似,但可對(duì)命名空間進(jìn)行操作。在此舉例中,std 是一個(gè) crate (~ a library),cmp 是一個(gè) module(~ a source file),以及 min 是個(gè)函數(shù):

let least = std::cmp::min(3, 8); // this is 3

use 指令可用于從其他命名空間中「引入范圍」命名:

use std::cmp::min;let least = min(7, 1); // this is 1

在 use 指令中,花括號(hào)還有另一個(gè)含義:「globs」,因此可以同時(shí)導(dǎo)入 min 以及 max:

// this works:use std::cmp::min;use std::cmp::max;// this also works:use std::cmp::{min, max};// this also works!use std::{cmp::min, cmp::max};

通配符(*)允許從命名空間導(dǎo)入符號(hào):

// this brings `min` and `max` in scope, and many other thingsuse std::cmp::*;

Types 也是命名空間和方法,它可以作為常規(guī)函數(shù)調(diào)用:

let x = 'amos'.len(); // this is 4let x = str::len('amos'); // this is also 4

str 是一個(gè)基元數(shù)據(jù)類(lèi)型,但在默認(rèn)情況下,許多非基元數(shù)據(jù)類(lèi)型也在作用域中。

// `Vec` is a regular struct, not a primitive typelet v = Vec::new();// this is exactly the same code, but with the *full* path to `Vec`let v = std::vec::Vec::new()

至于為什么可行,因?yàn)?Rust 在每個(gè)模塊的開(kāi)頭都插入了:

use std::prelude::v1::*;

再說(shuō)說(shuō)結(jié)構(gòu)體

使用 struct 關(guān)鍵字聲明結(jié)構(gòu)體:

struct Vec2 {    x: f64, // 64-bit floating point, aka 'double precision'    y: f64,}

可以使用結(jié)構(gòu)語(yǔ)句初始化:

let v1 = Vec2 { x: 1.0, y: 3.0 };let v2 = Vec2 { y: 2.0, x: 4.0 };// the order does not matter, only the names do

有一個(gè)快捷方式可以從另一個(gè)結(jié)構(gòu)體初始化本結(jié)構(gòu)體的其余字段:

let v3 = Vec2 {    x: 14.0,    ..v2};

這就是所謂的「結(jié)構(gòu)體更新語(yǔ)法」只能發(fā)生在最后一個(gè)位置,不能在其后面再跟一個(gè)逗號(hào)。

注意其余字段可以表示所有字段:

let v4 = Vec2 { ..v3 };

結(jié)構(gòu)體與元組一樣,可以被解構(gòu)。例如一個(gè)有效的 let 模式:

let (left, right) = slice.split_at(middle);let v = Vec2 { x: 3.0, y: 6.0 };let Vec2 { x, y } = v;// `x` is now 3.0, `y` is now `6.0`let Vec2 { x, .. } = v;// this throws away `v.y`

讓 let 模式在 if 里可以作為條件:

struct Number { odd: bool, value: i32,}fn main() { let one = Number { odd: true, value: 1 }; let two = Number { odd: false, value: 2 }; print_number(one); print_number(two);}fn print_number(n: Number) { if let Number { odd: true, value } = n { println!('Odd number: {}', value); } else if let Number { odd: false, value } = n { println!('Even number: {}', value); }}// this prints:// Odd number: 1// Even number: 2

多分支的 match 也是條件模式,就像 if let:

fn print_number(n: Number) {    match n {        Number { odd: true, value } => println!('Odd number: {}', value),        Number { odd: false, value } => println!('Even number: {}', value),    }}// this prints the same as before

match 必須是囊括所有情況的的:至少需要匹配一個(gè)條件分支。

fn print_number(n: Number) { match n { Number { value: 1, .. } => println!('One'), Number { value: 2, .. } => println!('Two'), Number { value, .. } => println!('{}', value), // if that last arm didn't exist, we would get a compile-time error }}
fn print_number(n: Number) {    match n.value {        1 => println!('One'),        2 => println!('Two'),        _ => println!('{}', n.value),    }}

Type 別名

我們可以使用 type 關(guān)鍵字聲明另一類(lèi)型的別名,然后就可以像使用一個(gè)真正的類(lèi)型一樣使用這種類(lèi)型。例如定義 Name 這種數(shù)據(jù)類(lèi)型為字符串,后面就可以直接使用 Name 這種類(lèi)型了。
你可以在方法中聲明不同的數(shù)據(jù)類(lèi)型:

struct Number { odd: bool, value: i32,}impl Number { fn is_strictly_positive(self) -> bool { self.value > 0 }}
fn main() {    let minus_two = Number {        odd: false,        value: -2,    };    println!('positive? {}', minus_two.is_strictly_positive());    // this prints 'positive? false'}
fn main() { let n = Number { odd: true, value: 17, }; n.odd = false; // error: cannot assign to `n.odd`, // as `n` is not declared to be mutable}
fn main() {    let n = Number {        odd: true,        value: 17,    };    n = Number {        odd: false,        value: 22,    }; // error: cannot assign twice to immutable variable `n`}

mut 可以使變量聲明變?yōu)榭勺兊模?/p>

fn main() { let mut n = Number { odd: true, value: 17, } n.value = 19; // all good}

Traits 描述的是多種數(shù)據(jù)類(lèi)型的共同點(diǎn):

trait Signed {    fn is_strictly_negative(self) -> bool;}
impl Signed for Number { fn is_strictly_negative(self) -> bool { self.value < 0 }}fn main() { let n = Number { odd: false, value: -44 }; println!('{}', n.is_strictly_negative()); // prints 'true'}
impl Signed for i32 {    fn is_strictly_negative(self) -> bool {        self < 0    }}fn main() {    let n: i32 = -44;    println!('{}', n.is_strictly_negative()); // prints 'true'}
impl std::ops::Neg for Number { type Output = Self; fn neg(self) -> Self { Self { value: -self.value, odd: self.odd, } }}
fn main() {    let a: i32 = 15;    let b = a; // `a` is copied    let c = a; // `a` is copied again}

下面的代碼也是能運(yùn)行的:

fn print_i32(x: i32) { println!('x = {}', x);}fn main() { let a: i32 = 15; print_i32(a); // `a` is copied print_i32(a); // `a` is copied again}
fn main() {    let n = Number { odd: true, value: 51 };    let m = n; // `n` is moved into `m`    let o = n; // error: use of moved value: `n`}
fn print_number(n: Number) { println!('{} number {}', if n.odd { 'odd' } else { 'even' }, n.value);}fn main() { let n = Number { odd: true, value: 51 }; print_number(n); // `n` is moved print_number(n); // error: use of moved value: `n`}
fn print_number(n: &Number) {    println!('{} number {}', if n.odd { 'odd' } else { 'even' }, n.value);}fn main() {    let n = Number { odd: true, value: 51 };    print_number(&n); // `n` is borrowed for the time of the call    print_number(&n); // `n` is borrowed again}
fn invert(n: &mut Number) { n.value = -n.value;}fn print_number(n: &Number) { println!('{} number {}', if n.odd { 'odd' } else { 'even' }, n.value);}fn main() { // this time, `n` is mutable let mut n = Number { odd: true, value: 51 }; print_number(&n); invert(&mut n); // `n is borrowed mutably - everything is explicit print_number(&n);}
// note: `Copy` requires that `Clone` is implemented tooimpl std::clone::Clone for Number {    fn clone(&self) -> Self {        Self { ..*self }    }}impl std::marker::Copy for Number {}

現(xiàn)在 Clone 仍然可以用于:

fn main() { let n = Number { odd: true, value: 51 }; let m = n.clone(); let o = n.clone();}
fn main() {    let n = Number { odd: true, value: 51 };    let m = n; // `m` is a copy of `n`    let o = n; // same. `n` is neither moved nor borrowed.}

有一些traits很常見(jiàn),它們可以通過(guò)使用derive 屬性自動(dòng)實(shí)現(xiàn):

#[derive(Clone, Copy)]struct Number { odd: bool, value: i32,}// this expands to `impl Clone for Number` and `impl Copy for Number` blocks.

看上去,整篇教程都在使用大量代碼解釋 Rust 的各種語(yǔ)句與用法。可能我們會(huì)感覺(jué)博客結(jié)構(gòu)不是太明確,但是實(shí)例驅(qū)動(dòng)的代碼學(xué)習(xí)確實(shí)更加高效。尤其是對(duì)于那些有一些編程基礎(chǔ)的同學(xué),他們可以快速抓住 Rust 語(yǔ)言的特點(diǎn)與邏輯。

最后,這篇文章并沒(méi)有展示博客所有的內(nèi)容,如果讀者想真正入門(mén) Rust 語(yǔ)言,推薦可以查閱原博客。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章