文だけでなく式で終わることもできるのが最大のポイントか。
成果物
コード
0. 宣言
main.rs
fn main() { sub_fn(); } fn sub_fn() { println!("Hello Rust !!"); }
$ rustc main.rs $ ./main Hello Rust !!
- 宣言には
fn
が必要 - 宣言する位置はmainの下でもOK
- 名前はスネークケース(すべて小文字で
_
を単語区切文字とする)
1. 引数
main.rs
fn main() { show_age(66); } fn show_age(age: i32) { println!("My age is {}.", age); }
もし関数の引数に型を指定しなければ、以下エラー。
error: expected one of `:` or `@`, found `)` --> main.rs:8:16 | 8 | fn show_age(age) { | ^ expected one of `:` or `@` here
1-1. 複数
fn main() { show_coordinate(12, 34); } fn show_coordinate(x:i32, y:i32) { println!("({}, {})", x, y); }
複数の引数があるときはカンマ,
で区切る。
2. 式
Rustの関数は、最後が文で終わるものだけでなく、式で終わるものも作れる。(Pythonでいうlambda式のように式で終わるものも作れる)
2-0. 文と式
対象 | 値 | 終端 |
---|---|---|
文 | 返さない | ; |
式 | 返す | ; なし |
終端に;
を付与すると文になる。たとえば1 + 1
は式だが、1 + 1;
は文になる。罠になりそう。
fn main() { let x = 1; let y = (let z = 2); // error: expected expression, found statement (`let`) }
error: expected expression, found statement (`let`) --> main.rs:7:14 | 7 | let y = (let z = 2); | ^^^ expected expression | = note: variable declaration using `let` is a statement error: aborting due to previous error
式を期待していたが、文が見つかったときのエラー。左辺は値が返ってくることを期待しているが、右辺が文であり、文は値を返さないため、エラーになる。
2-0-1. 関数の最後が式
以下のようにすると成功する。
fn main() { let x = 1; let y = { x + 1 }; println!("{} {}", x, y); // 1 2 }
x + 1
の終端に;
がないことに注目。これは式である。そしてブロック{}
で新たなスコープを作っている。{}
も式。ちなみに関数呼出も式。
2-0-2. 関数の最後が文
もし式x + 1
の終端に;
をつけて文にすると?
fn main() { let x = 1; let y = { x + 1; }; println!("{} {}", x, y); // 1 2 }
$ rustc main.rs error[E0277]: `()` doesn't implement `std::fmt::Display` --> main.rs:9:26 | 9 | println!("{} {}", x, y); | ^ `()` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: required by `std::fmt::Display::fmt` error: aborting due to previous error For more information about this error, try `rustc --explain E0277`.
フォーマットを変更すると、警告は出るものの実行できた。
fn main() { let x = 1; let y = { x + 1; }; println!("{} {:?}", x, y); }
$ rustc main.rs warning: unused arithmetic operation that must be used --> main.rs:8:15 | 8 | let y = { x + 1; }; | ^^^^^ | = note: #[warn(unused_must_use)] on by default
$ ./main 1 ()
()
って何? 要素数がゼロのタプル? わからん。
3. 戻り値
fn main() { let x = five(); // `let = 5;`と同義 println!("{}", x); } fn five() -> i32 { 5 }
five()
関数の最後に;
がないので式である。式は値を返す。関数で値を返すには戻り値を宣言する必要がある。fn 関数名() -> i32
のi32
がそれ。名前はつけず型を指定する。
代入せず直接わたすこともできる。
fn main() { println!("{}", five()); } fn five() -> i32 { 5 }
4. 引数と戻り値
fn main() { let x = add_one(9); println!("{}", x); } fn add_one(x: i32) -> i32 { x + 1 }
$ rustc main.rs $ ./main 10
add_one
関数の最後であるx + 1
の終端に;
をつけて文にすると、以下エラー。
$ rustc main.rs error[E0308]: mismatched types --> main.rs:9:23 | 9 | fn add_one(x: i32) -> i32 { | ------- ^^^ expected i32, found () | | | this function's body doesn't return 10 | x + 1; | - help: consider removing this semicolon | = note: expected type `i32` found type `()` error: aborting due to previous error For more information about this error, try `rustc --explain E0308`.
「戻り値としてi32
を期待していたのに()
が見つかった」と怒られる。
だが、文だとしてもreturn
すれば成功した。
fn add_one(x: i32) -> i32 { return x + 1; }
これはC/C++言語でおなじみ。
参考
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
$ uname -a Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
前回まで
- Rustを学んでみたい(プログラミング言語)
- Rustの環境構築
- RustでHelloWorld
- Rustの和訳ドキュメント
- Cargoでプロジェクト作成・ビルド・実行
- クレートとは?
- Rustで関数を使ってみる
- Rustでモジュールを使ってみる
- Rustで乱数を生成する(rand)
- Rustで標準入力する(std::io::stdin().read_line())
- RustでMatch判定する(match)
- Rustでprintとread_lineを1行にする方法
- Rustで数当てゲーム
- クレート名にドット.が使えない
- Rustの変数と可変性(let, mut) error[E0384]: cannot assign twice to immutable variable
x
- Rustのimmutable束縛とconst定数の違い
- RustのREPL、evcxrのインストールに失敗した
- Rustでコンパイルするときの変数未使用warningを消す
- Rustの変数(再代入、再宣言(シャドーイング))
- Rustのシャドーイングについて
- イミュータブルについて(副作用)
- Rustの定数(const)
- Rustのデータ型(数値)
- Rustのデータ型(論理)
- Rustのデータ型(文字)
- Rustのデータ型(タプル)
- Rustのデータ型(配列)