Rust 語法基礎

notice

Rust 還沒到1.0,開發很快,請看官方文檔

語法基礎

Rust的語法和其餘C-family 語言很類似。html

if while 這類的控制結構和其餘類c語言最大的不一樣是Rust中不須要在條件加括號, 可是,代碼塊要用大括號。訪問命名空間函數,變量要用::程序員

簡單的循環express

rustfn main() {
    /* A simple loop */
    loop {
        // A tricky calculation
        if universe::recalibrate() {
            return;
        }
    }
}

使用let 關鍵字建立局部變量,變量默認是不可變的。若是要建立可變變量使用 let mutide

let hi = "hi";
let mut count = 0;

while count < 10 {
    println!("count is {}", count);
    count += 1;
}

Rust 能夠本身推斷出變量的類型,固然咱們也能夠在變量名後冒號加變量類型指定變量類型,
另外,static 變量須要在定義的時候指定類型。函數

static MONSTER_FACTOR: f64 = 57.8;
let monster_size = MONSTER_FACTOR * 10.0;
let monster_size: int = 50;

局部變量也能夠覆蓋以前的申明,好比上面的例子中monster_size 最開始是 f64 類型,
第二個monster_size 是 int 類型。編譯代碼的話,會有warningoop

hellworld.rs:27:6: 27:18 warning: unused variable: `monster_size`, #[warn(unused_variable)] on by default
hellworld.rs:27     let monster_size = MONSTER_FACTOR * 10.0;
                        ^~~~~~~~~~~~

waring 說 monster_size 這個變量未使用(這種狀況通常是程序員程序寫錯了的)。
若是你想聲明一個未使用的變量,用不想用waring,能夠在變量前加一個下劃線消除waring。
例如: let _monster_size = 50;ui

Rust標識符以字母或者下劃線開頭,後邊能夠跟任意的字符序列,數字,或者下劃線。
首選的代碼風格是:對於函數,變量,模塊名使用小寫字母,使用下劃線提升可讀性,
自定義類型使用駝峯法。this

let my_variable = 100;
type MyType = int;     // primitive types are _not_ camel case

表達式和分號

Rust和它的前輩好比C在語法上有一個顯著的區別:許多在 C 中是語句的結構在 Rust 中是表達式,這讓代碼能夠更加簡潔。例如,你或許想寫一段這樣的代碼:指針

let price;
if item == "salad" {
    price = 3.50;
} else if item == "muffin" {
    price = 2.25;
} else {
    price = 2.00;
}

可是,在Rust裏,你沒必要重複寫price:code

let price =
    if item == "salad" {
        3.50
    } else if item == "muffin" {
        2.25
    } else {
        2.00
    };

兩段代碼徹底等價:都是經過條件判斷爲變量 price 賦值。注意第二段代碼中沒有分號。這是重點:在大括號括起來的代碼塊中,最後一個語句省略分號,會將最後語句的值做爲此代碼塊的返回值。

換句話說,Rust中的分號將忽略一個表達式的值。因此若是 if 分支是 { 4;},上例中的 price 將被賦值爲 () (nil 或者 void)。可是沒有這個分號,每一個分支將有一個不一樣的值,而且 price 被賦予選定分支的值。

歸納一下就是,除了聲明(使用 let 聲明變量,fn 聲明函數,任何頂層命名的項,如 traits, 枚舉類型 和static )的都是一個表達式,包括函數體。

fn is_four(x: int) -> bool {
   // 不須要return,最後一個表達式的結果,做爲返回值
   x == 4
}

原始類型和字面量

整形有 int 和 uint,是有符號整型和無符號整型,其餘變體,8位,16位,32位,64位等。能夠寫成10進制的形式(144),16進制 (0x90)八進制 (0o70)或者二進制(0b10010000)
,每一個整數類型都有相應的後綴,能夠用來指示字面量類型:i 表明int、u 表明uint、i8 表明i8類型。

若是沒有給整型指明後綴,Rust將根據上下文中的類型註釋和函數簽名來推斷整數類型。若是實在沒有任何類型信息,Rust將假定這個沒有後綴的字面量爲int型。

let a = 1;       // `a` 是 `int`
let b = 10i;     // `b` 是 `int`, 因爲 `i` 後綴
let c = 100u;    // `c` 是 `uint`
let d = 1000i32; // `d` 是 `i32`

有兩種浮點數類型:f32和f64。浮點數寫成0.0、1e6 或者2.1e-4這些形式。和整數同樣,浮點數字面量能夠推導出正確的類型。後綴f32 和f64 能夠用來指定一個字面量的類型。

關鍵字true 和false 指定bool 類型字面量。

字符,char 類型,是4個字節存儲的Unicode碼點,寫在兩個單引號間,如'x',和在C 中同樣,Rust使用反斜槓做爲字符轉義符,如\n,\r 以及\t。字符串字面量,寫在兩個雙引號之間,容許使用一樣的轉義符。

另外一方面,原始字符串(raw string)不處理任何轉義序列。它們這樣寫:r##"blah"##,在字符串開始的雙引號後面或者結束的雙引號前面有一個或者多個#,而且能夠在結束定界符前包含任何字符序列。

nil類型,寫作(),有惟一值。

操做符

Rust 的操做符包括基本上沒有什麼特別的地方。算數運算符有*/%+-(乘、除、取餘、加、和減),- 也是一個一員前置運算符,表示負數。和C 同樣,也支持位運算符>>, <<&|、和^

注意,若是應用於一個整數值,!反轉全部的位(像~ 在C 中的做用同樣)。

比較操做符有傳統的==!=<><=>=。短路(惰性)布爾操做符被寫做&&(與)和||(或)。

對於編譯時的類型轉化,Rust使用二元操做符as。將表達式放在左側,並將須要轉化的類型放在右邊,若是轉換有意義,就將表達式的結果轉換爲給定的類型。一般,as只能用於原始的整數類型或者指針,而且不能重載。transmute能夠對一樣大小和對齊的類型進行轉換。

let x: f64 = 4.0;
let y: uint = x as uint;
assert!(y == 4u);

語法擴展

Rust可讓你本身擴展語言沒有內建的功能,語法擴展的名字都是以!結尾的。標準庫定義了一些語法擴展,其中,最有用的是 format!,sprintf-like 的文本格式化程序,以及相關的宏家族 print!, println!write!

format! 借鑑了Python的語法,但包含了許多的printf規則。和printf不一樣的是,format! 當類型與參數不匹配的時候會返回編譯時的錯誤。

// `{}` 會打印類型的默認格式
println!("{} is {}", "the answer", 43);

// `{:?}` 能夠用於任何類型
println!("what is this thing: {:?}", mystery_object);

你可使用宏系統定義本身的語法擴展。更多的細節,macro tutorial,注意:宏特性尚未穩定下來,慎用。

控制結構

條件語句

if/else代碼例子, 大括號是必須的:

if false {
    println!("that's odd");
} else if true {
    println!("right");
} else {
    println!("neither true nor false");
}

if 後邊的條件必須是bool 類型,沒有隱式的類型轉換,若是if 語句後面的代碼塊有返回值,返回值的類型必須是同樣的。

fn signum(x: int) -> int {
    if x < 0 { -1 }
    else if x > 0 { 1 }
    else { 0 }
}

模式匹配

Rust的match 結構比C的switch更通用,易讀。
代碼:

match my_number {
  0     => println!("zero"),
  1 | 2 => println!("one or two"),
  3..10 => println!("three to ten"),
  _     => println!("something else")
}

與c的規則相反,Rust語言的match不須要用break明確的退出一個case,只有一個case會執行。

規則:

  • => 後邊是要執行的表達式
  • 能夠用管道| 匹配多個值
  • M..N 匹配範圍
  • _ 會匹配任何值
  • 每一個case以逗號分割
  • match 必需要有可以匹配到的值,若是傳入的值,不會匹配到任何case,編譯不會經過
  • =>後邊也支持塊表達式( block expression), 這種狀況每一個case後邊的逗號是可選的。
match my_number {
  0 => { println!("zero") }
  _ => { println!("something else") }
}

模式匹配頗有用的一個功能是解構(destructuring):

use std::f64;
use std::num::atan;
fn angle(vector: (f64, f64)) -> f64 {
    let pi = f64::consts::PI;
    match vector {
      (0.0, y) if y < 0.0 => 1.5 * pi,
      (0.0, _) => 0.5 * pi,
      (x, y) => atan(y / x)
    }
}

(f64, f64) 是一個元組,會做爲match的匹配值,每一個case的時候,vector會被解構,如 (0.0, y)表示匹配vector中,x是0.0的值,而且會把vector中y的值綁定到(0.0,y)中的y。(x, y) 會匹配任何兩個元素的元組,元組的值會綁定到x,y 。 而(0.0,_) 第二個元素值會被丟棄。
matchpattern guard 中能夠在case寫 if EXPR , angle函數中的第一個case就是,只有if 後的表達式爲true的時候,case才被執行。 可使用variable @ pattern`將匹配到的值賦給變量,例如:

match age {
    a @ 0..20 => println!("{} years old", a),
    _ => println!("older than 21")
}

let 也支持模式匹配,好比:
let (a, b) = get_tuple_of_two_ints();

Loops 循環

while表示當給定的條件是true是,會一直循環迭代。關鍵字break 跳出循環,continue跳出當前迭代,進行下一次迭代。

let mut cake_amount = 8;
while cake_amount > 0 {
    cake_amount -= 1;
}

loop表示無限循環,是while true更好的方式:

let mut x = 5u;
loop {
    x += x - 3;
    if x % 5 == 0 { break; } 
    println!("{}", x);
}

官方tutorial: http://static.rust-lang.org/doc/master/tutorial.html

相關文章
相關標籤/搜索