OS: Windows 10
Editor: Visual Studio Code
Rust version: 1.63.0
認識一門新的程式語言,必免不了幾個步驟,今天來試著理解Rust中:
在Rust中宣告一個變數:
let x = 100;
這在近年熱門的的程式語言中都有類似的寫法或是語法糖,由編譯器去判斷型別是甚麼,其他與類似的寫法:
// C++
auto x = 100;
// C#
var x = 100;
// Golang
var x = 100
在沒有特定指定型別的情況下,通常會被判定為Int32
,在這裡我想知道,let x = 100
是不是真的是Int32
,於是開始找看看有沒有內建的函式,可以幫我告訴我型別,後來看到了一個有趣的!
我們可以刻意寫一個error讓Rust compiler告訴我們型別是甚麼,於是:
let x = 100;
x.what_is_this_type(); // 這是為了讓compiler故意丟error回來
然後compiler告訴我:
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0599]: no method named `what_is_this_type` found for type `{integer}` in the current scope
--> src\main.rs:3:7
|
3 | x.what_is_this_type();
| ^^^^^^^^^^^^^^^^^ method not found in `{integer}`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `basic` due to previous error
知道是integar
了,但是幾位元的,在這裡找到了答案,在Summary的地方。
Integer literals whose type is unconstrained will default to i32
當然!我們也可以在宣告的時候,指定型別:
let x: u8 = 100;
然後一樣讓compiler告訴我們這個型別
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0599]: no method named `what_is_this_type` found for type `u8` in the current scope
--> src\main.rs:3:7
|
3 | x.what_is_this_type();
| ^^^^^^^^^^^^^^^^^ method not found in `u8`
For more information about this error, try `rustc --explain E0599`.
嗯!確定是UInt8
!
再來就是常見的例子:
let x = 100;
x += 50;
println!("x is {}", x);
編譯!
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0384]: cannot assign twice to immutable variable `x`
--> src\main.rs:3:5
|
2 | let x = 100;
| -
| |
| first assignment to `x`
| help: consider making this binding mutable: `mut x`
3 | x += 50;
| ^^^^^^^ cannot assign twice to immutable variable
For more information about this error, try `rustc --explain E0384`.
然後compiler丟了錯誤給我....(哭)
這個就是Rust跟其他語言一開始就不太一樣的地方了,let x
的話這個變數是不可變的,如果要讓上面的範例可以成功編譯的話需要加上mut
:
let mut x = 100;
x += 50;
println!("x is {}", x);
上面的例子讓我想知道一件事:那不可變數跟常數有甚麼差別呢?找了一些文件,這邊寫到:
首先,你無法在使用常數使用 mut,常數不是預設不可變,它們永遠都不可變。如果你使用 const 宣告而非 let 的話,你必須指明型別。
也就是說如果要宣告常,需要這樣:
const const_x: u8 = 100;
但這會丟Warning給你,要求你改成大寫:
const CONST_X: u8 = 100;
PS: 沒記錯的話,在Golang常數用小寫會直接丟error。
官方教學的這個小節告訴了我們一件事!
如果我們這樣宣告,那這樣寫會發生甚麼事呢?
let mut spaces = " ";
spaces = spaces.len();
答案是會直接丟出error,因為編譯器已經知道這個變數是某個型別了,不能直接換成其他型別。
關於基礎型別(Primitive Type),尤其是整數!會有需要考慮到溢位的可能,但官方教學告訴了我們一些有趣的事:
const NUM: u8 = 255;
let mut x = 1;
x += NUM;
println!("x is {}", x);
直接下
cargo run
Compiler會在編譯期間告訴我們overflow了
thread 'main' panicked at 'attempt to add with overflow', src\main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
但是如果是在release
模式下編譯的話:
cargo run --release
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
Finished release [optimized] target(s) in 0.35s
Running `target\release\basic.exe`
x is 0
Rust會把它變成二的補數!
詳情請看這裡。
這裡指的是基本型的轉型,一樣拿整數加減為舉例:
let x: u8 = 100;
let mut y: i32 = 1024;
y += x;
println!("y is {}", x);
Compiler會直接告訴你,型別不一樣,不能直接相加
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0308]: mismatched types
--> src\main.rs:4:10
|
4 | y += x;
| ^ expected `i32`, found `u8`
error[E0277]: cannot add-assign `u8` to `i32`
--> src\main.rs:4:7
|
4 | y += x;
| ^^ no implementation for `i32 += u8`
|
= help: the trait `AddAssign<u8>` is not implemented for `i32`
= help: the following other types implement trait `AddAssign<Rhs>`:
<f32 as AddAssign<&f32>>
<f32 as AddAssign>
<f64 as AddAssign<&f64>>
<f64 as AddAssign>
<i128 as AddAssign<&i128>>
<i128 as AddAssign>
<i16 as AddAssign<&i16>>
<i16 as AddAssign>
and 20 others
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
這個就不像C++那樣,Compiler會幫你隱式轉換(implicit conversion),需要自己轉型,基本型別轉型的話是像這樣:
let x: u8 = 100;
let mut y: i32 = 1024;
y += x as i32; // 這裡轉型
println!("y is {}", y);