<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
今天我們來學習 Rust 中的函數,最後會捎帶介紹一下如何在 Rust 中寫註釋。也是比較輕量級的一節,大家快速過一下即可。
函數本身是各個語言都支援的型別,我們此前已經多次使用 fn main()
這個函數來承載業務邏輯,fn
可以用來宣告一個函數,而 main
函數跟其他語言一樣,可以理解為程式啟動的【起點】,一切邏輯從這裡開始。
Rust 本身的命名規範是【snake case】,即下劃線 + 小寫,這個其實各個語言都有自己規範,分清楚環境即可。
fn main() { println!("Hello, world!"); another_function(); } fn another_function() { println!("Another function."); }
這裡的 another_function 就是個沒有入參,沒有出參的函數,命名遵循 snake case,很好理解。
Rust 中的函數跟其他語言是一樣的,用 fn
來宣告,後面加上函數名,小括號裡面可以放入參,之後可以定義出參,最後用花括號來承載函數體。呼叫函數也不復雜,函數名後面跟上小括號+引數即可,注意 scope 就行,這裡是因為我們的 another_function
就在當前包下,所以直接就那來呼叫。呼叫的時候要保證【函數所在的 scope 是對 caller 可見】的即可。
我們在 rust-learn 專案下通過 cargo new functions
新建一個專案,試一下上面的程式碼:
$ cargo run =============================== Compiling functions v0.1.0 (/Users/ag9920/go/src/github.com/ag9920/rust-learn/functions) Finished dev [unoptimized + debuginfo] target(s) in 1.76s Running `target/debug/functions` Hello, world! Another function.
另外需要強調一點,Rust 檔案內函數定義並不要求順序,只要定義在 scope 內就能解析,比如 main 函數先於 another_function 定義是沒問題的。
還是基於我們此前的 another_function,我們嘗試加一下入參,看看應該怎麼做:
fn main() { another_function(5); } fn another_function(x: i32) { println!("The value of x is: {x}"); }
執行過後,結果如下:
$ cargo run =============================== Compiling functions v0.1.0 (/Users/ag9920/go/src/github.com/ag9920/rust-learn/functions) Finished dev [unoptimized + debuginfo] target(s) in 0.62s Running `target/debug/functions` The value of x is: 5
此時 another_function 增加了一個引數 x,我們宣告其型別為 i32。在 main 函數中呼叫的時候,傳入我們的引數 5,最後被列印出來。
可能有的地方會特意提一下這兩個概念:
但通常說起來的時候我們不太區分,對我們來說統一叫【引數】即可。
上面範例中,我們定義入參是這樣的:fn another_function(x: i32)
。
這裡【冒號 + 空格 + 型別】的寫法我們已經見過很多次了,那能不能不帶型別呢?我直接寫個 fn another_function(x)
,具體格式留給編譯器來推斷 ok 不?
在 Rust 中這件事是不 ok的,按照規範,對於每個入參你都必須清晰地指明【型別】,這樣編譯器也省事,報錯時也能更精準給出相關判斷。如果我們需要多個入參,用【逗號】分隔即可:
fn main() { print_labeled_measurement(5, 'h'); } fn print_labeled_measurement(value: i32, unit_label: char) { println!("The measurement is: {value}{unit_label}"); }
執行結果如下:
$ cargo run ======================== Compiling functions v0.1.0 (/Users/ag9920/go/src/github.com/ag9920/rust-learn/functions) Finished dev [unoptimized + debuginfo] target(s) in 0.87s Running `target/debug/functions` The measurement is: 5h
Rust 本身是一個基於表示式的語言,所以這兩個概念我們先區分一下,語句(statements),表示式(expressions)是什麼區別?
Statements are instructions that perform some action and do not return a value. Expressions evaluate to a resulting value.
簡單說,就是看有沒有【返回值】,無返回值的是語句,有返回值的是表示式,表示式可以是一個語句的組成部分。
舉個例子:let y = 6;
這就是一個【語句】,而 6
就是一個【表示式】,在 Rust 中你是不能做 let x = (let y = 6);
這樣的操作的,因為括號裡面的部分是個語句,語句沒有返回值,那麼該拿什麼給 x 賦值呢?
所以,不像其他語言,可能允許類似 x = y = 6
,這樣讓 x 和 y 都賦值了 6。Rust 是不允許這樣的。
fn main() { let y = { let x = 3; x + 1 }; println!("The value of y is: {y}"); }
比如上面這個案例,在花括號這個 scope 中,我們定義了 x 變數,將其賦值為 3,然後將 x+1
這個表示式返回,所以 y 被賦值為 4。
花括號裡面的部分就是一個表示式,返回了 4 。注意 x + 1
的結尾沒有分號,這也是表示式的特徵。這裡千萬不能加分號,要想清楚。如果你想用一個表示式返回,就不加分號。加了之後變成了語句,但也不會返回什麼東西。
Rust 函數體則是由一系列【語句】+ 預設可選的一個【表示式】組成。為什麼是可選的?因為類似我們前面的函數,沒有返回值,不需要最後的這個【表示式】。
Rust 是不支援命名返回值的(這一點跟 Golang 有所不同),函數定義出參的部分需要用【箭頭符號】顯式地宣告。
不像很多函數要求顯式的 return 返回值,Rust 預設會返回最後的表示式的值。當然我們如果想 early return 也是 ok的,但大多數函數不會寫 return 這個關鍵字,而是隱式地返回最後一個表示式。我們來看一個例子:
fn five() -> i32 { 5 } fn main() { let x = five(); println!("The value of x is: {x}"); }
這裡的 five 函數非常簡單,只有一個 5 作為表示式返回,不需要 return。
這是完全合法的 Rust 函數,出參只有一個 i32。我們加上入參,再看一個例子:
fn main() { let x = plus_one(5); println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { x + 1 }
此時我們有一個 i32 入參,也有一個 i32 出參,函數體是一個簡單的表示式 x + 1。執行上面程式碼列印的結果是 The value of x is: 6
,符合預期。
我們試試給 x + 1
後面加上個分號看看:
fn main() { let x = plus_one(5); println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { x + 1; }
此時執行結果果然報錯(這個不是執行時報錯,是編譯階段識別的)
$ cargo run ==================== Compiling functions v0.1.0 (/Users/ag9920/go/src/github.com/ag9920/rust-learn/functions) error[E0308]: mismatched types --> src/main.rs:7:24 | 7 | fn plus_one(x: i32) -> i32 { | -------- ^^^ expected `i32`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1; | - help: remove this semicolon For more information about this error, try `rustc --explain E0308`. error: could not compile `functions` due to previous error
問題在於,plus_one 說了會有返回值 i32,但到最後也沒發現【表示式】,此時 Rust 預設會返回 () 一個空的 tuple(我們上一節講過,這個叫 unit),所以報錯叫做【 mismatched types】,而不是類似【no return value】,這裡是不是就理解了?
沒有返回值的函數,本質上是返回了一個 unit:
// Functions that "don't" return a value, actually return the unit type `()` fn fizzbuzz(n: u32) -> () { if is_divisible_by(n, 15) { println!("fizzbuzz"); } else if is_divisible_by(n, 3) { println!("fizz"); } else if is_divisible_by(n, 5) { println!("buzz"); } else { println!("{}", n); } }
問題又來了,那 Rust 能不能支援多個出參呢?類似 Golang 中的:
func addsub(x, y int) (int, int) { return x + y, x - y }
其實 Rust 對這個事情的解決方案就是我們已經見過多次的 tuple:
fn addsub(x: isize, y: isize) -> (isize, isize) { (x + y, x - y) } fn my_func() -> (u8, bool) { (1, true) }
圓括號千萬不能少,記住我們 return 的是個 tuple,不是多個單獨的值。
這裡有一個可執行的 online 範例,大家可以複習一下 tuple,結合多個返回值體會一下:
fn swap(x: i32, y: i32) -> (i32, i32) { return (y, x); } fn main() { // return a tuple of return values let result = swap(123, 321); println!("{} {}", result.0, result.1); // destructure the tuple into two variables names let (a, b) = swap(result.0, result.1); println!("{} {}", a, b); }
註釋其實比較簡單,我們快速提一下。
Rust 的行註釋就是常見的 //
雙斜槓,如果一行放不下,需要多行的話,也需要在每一行前面加.
fn main() { // I'm feeling lucky today let lucky_number = 7; }
檔案註釋有些許的區別,這裡需要用 ///
三斜槓,這樣能夠輔助生成 HTML 檔案。
/// Adds one to the number given. /// /// # Examples /// /// ``` /// let arg = 5; /// let answer = my_crate::add_one(arg); /// /// assert_eq!(6, answer); /// ``` pub fn add_one(x: i32) -> i32 { x + 1 }
以上就是Rust 入門之函數和註釋範例詳解的詳細內容,更多關於Rust 函數註釋的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45