iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
0
自我挑戰組

WebAssembly + Rust 的前端應用系列 第 10

[Day 10] Rust Functions 函式

又到了每天學一點 Rust 的時間,在進入今天的主題之前為了讓程式寫起來可以更方便好管理我們先來介紹一下簡單的 Module 而我其實在前面的範例就已經是這樣做了,因此防止未來有機會搞混各位所以我就先稍微講一下。

Module

Rust 的 entry point 是 main 這個函式,而筆者在寫的時候其實就已經把函式都拆開來在不同的檔案裡面了,所以我的函式名稱都不是用 main 來命名會跟官方的範例有一點出入。這邊我就直接帶各位看一下我的專案結構

https://ithelp.ithome.com.tw/upload/images/20190925/20119807YrOIQssH6q.png

那麼我們應該要怎麼樣在 main 裡面呼叫我在其他檔案的函式呢?首先我們產生一個新的檔案叫做 my_functions.rs 並且宣告一個新的函式,

檔案名稱:my_functions.rs
fn hello_world() {
  println!("Hello World");
}

接著我們回到 main.rs 來試著呼叫這支程式。

檔案名稱 main.rs
mod my_functions;

fn main() {
  my_functions::hello_world();
}

其實已經差不多了但是,這個時候執行的話會跳出錯誤。

檔案名稱 main.rs
mod my_functions;

fn main() {
  my_functions::hello_world();
                ^^^^^^^^^^^ function `hello_world` is private
}

原因是 my_functions 裡面的這支程式是 private 的為了要讓其他程式可以使用他必須把它變成 public 的,

檔案名稱:my_functions.rs
pub fn hello_world() {
  println!("Hello World");
}

那麼再執行一次就會正常顯示了。

另外這邊還有一個觀念是 rust 的 module 這邊稍微提下概念

  • mod 宣告一個 module
  • pub 輸出
  • use 載入

而我這邊在 main.rs 裡面使用 mod 時 Rust 的編譯器會自動去找命名為 X.rs 或 X/mod.rs 的檔案,要講詳細的話篇幅比較多今天還是把重點放在函式本身如何使用之後再一起介紹吧!

那麼廢話不多說馬上就來進入今天的主題

函式參數

之前的範例基本上函式都沒有帶任何的參數所以這邊我們直接上個需要參數的範例

fn fn_with_parameters(x: i32, y: i32) {
  println!("The value of x is: {}", x);
  println!("The value of y is: {}", y);
}

接著我們在 main 裡面執行,

fn main() {
  fn_with_parameters(5, 5);
  // The value of x is: 5
  // The value of y is: 5
}

另外要注意的是函式的參數型態,如果型態不符就會直接報錯例如,

fn main() {
  fn_with_parameters('5', 5);
                     ^^^ expected i32, found char
  // The value of x is: 5
  // The value of y is: 5
}

Note: 函式參數必須給他指定的型態,如果傳進來的參數型態錯誤時就會直接報錯。

expression vs statement

Rust 的一個重要概念就是他是 expression-based language ,而 expression 意思就是說他一定會有返回的值反之 statement 則無返回值。這樣設計的目的可以讓我們的程式可以很好的被組合來使用也非常符合 functional programing 的概念。

那麼既然有這樣的特性我們就來試試看是不是真的如此,

fn expression_based() {
  let foo = if 1 == 0 {
    "bar"
  } else {
    "baz"
  };
  println!("The value of foo is: {}", foo);
  // The value of foo is: baz
}

由這個例子我們發現在 {} 在裡面的字串會被返回。

Note: 函式是屬於 statement 的別搞錯了喔。

函式包含 expression 和 statement

Rust 的函式中可以包含很多的 expression 或是 statement 剛剛所講的 expression 其實就是 {} 而其都一定會有返回值,但是 statement 則一定不會有返回值,舉個例子

fn main() {
    let x = (let y = 6);
}

這裡會錯因為宣告變數是 statement 而他不會返回 y 的值因此會報錯,不像我們在其他的程式語言例如 javascript 可以這樣寫,

let x = y = 1;

Note: 這是 javascript。

但是如果把它改成 expression 則可以例如

fn statement_test() {
  let x = {
    let y = 6;
    y
  };
  println!("The value of x is: {}", x);
  // The value of x is: 6
}

expression 返回 y 所以 x 也跟 y 一樣為 6,另外一點值得注意的是 expression 的結尾設計上並沒有分號這點要稍加留意囉

函式返回值

剛剛花了很多時間理解 expression 跟 statement 那麼既然函式本身也是 statement 那麼要怎麼讓他返回值呢?我們可以這樣寫,

fn five() -> i32 {
    5
}

如上的函式會返回 5 ,聰明的各位很容易看得出來其實只要把函式加上 -> 還有後面是他要返回的值的型態,那麼就會跟 expression 一樣了。

接著我們把剛剛學到的函式參數跟返回值合併起來我們就可以寫出這樣的函式,

fn add(x: i32, y: i32) -> i32 {
  x + y
}

如果不用 expression 也可以這樣寫

pub fn add(x: i32, y: i32) -> i32 {
  return x + y;
}

當然筆者是比較偏好用 expression 因為能寫越少程式碼越好啊/images/emoticon/emoticon01.gif

小結

今天學會了簡單的 Rust module 的以及如何區分 expression 跟 statement,接著下一篇會帶各位學習 Rust 的基本流程控制的方式也就是 if else, for loop 等等。

那麼感謝你的收看我們明天見!

最後一樣有問題歡迎發問

/images/emoticon/emoticon07.gif

參考網站

rust-scala-part
im_confused_by_what_an_expression_oriented


上一篇
[DAY 9] Rust Data Types 資料型態 (2)
下一篇
[Day 11] Rust Control Flow 控制流程
系列文
WebAssembly + Rust 的前端應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言