【Rust】がばがばRust独学 - 2. 関数
Rustの公式ドキュメントを通して、Rustを独学していく記事になります。(がば要素あり)
今回は、関数について学びつつ、気になった点をコード確認した結果を記事にしています。
- versions
$ rustc --version rustc 1.40.0 (73528e339 2019-12-16)
関数
example
fn plus_one(x: i32) -> i32 { x + 1 } fn main() { let x = plus_one(3); println!("x -> {}", x); }
x -> 4
基本形
fn
から始まり、関数名(下記では hogera
)によって関数を定義し、hogera()
により関数を呼び出します。
fn main() { println!("Hello World!"); hogera(); } fn hogera() { println!("Another funciton!"); }
Hello World! Another funciton!
また、関数の順序はなさそうです。
fn hogera() { println!("Another funciton!"); } fn main() { println!("Hello World!"); hogera(); }
Hello World! Another funciton!
引数
x: i32
のように、引数名と型を定義することによって、引数を利用できます。
fn main() { println!("Hello World!"); hogera(256); } fn hogera(x: i32) { println!("Number -> {}", x); }
もし、型がない場合は、型をつけろよと怒られます。
if this was a parameter name, give it a type
fn main() { println!("Hello World!"); hogera(256); } fn hogera(x) { println!("Number -> {}", x); }
error: expected one of `:`, `@`, or `|`, found `)` --> demo.rs:6:12 | 6 | fn hogera(x) { | ^ expected one of `:`, `@`, or `|` here | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this was a parameter name, give it a type | 6 | fn hogera(x: TypeName) { | ^^^^^^^^^^^ help: if this is a type, explicitly ignore the parameter name | 6 | fn hogera(_: x) { | ^^^^ error: aborting due to previous error
複数渡す場合は、 ,
区切りによって定義可能です。
fn main() { println!("Hello World!"); hogera(256, 512); } fn hogera(x: i32, y: i32) { println!("x -> {}", x); println!("y -> {}", y); }
Hello World! x -> 256 y -> 512
Expension、ブロック( {}
)
Rustは式ベースの言語です。
Rust is an expression-based language
新しいスコープを生成するためにブロック({}
)を使用します。
下記の場合、 x
に対するスコープの違いにより、main
関数における x
と、y
のブロック(式)によるスコープの違いにより、y
は 5 + 10
となります。
fn main() { let x = 3; let y = { let x = 5; x + 10 }; println!("x -> {}, y -> {}", x, y); }
x -> 3, y -> 15
また、 ブロック内でxの定義 let x
をしない場合は、ブロック外の変数をスコープして使用します。
fn main() { let x = 3; let y = { x + 10 }; println!("x -> {}, y -> {}", x, y); }
x -> 3, y -> 13
返り値
返り値の型は、下記例では i32
のように、関数にアロー( ->
)を利用して記載することが可能です。また、返り値には文末のセミコロンが不要です。
fn two() -> i32 { 2 } fn main() { let x = two(); println!("x -> {}", x); }
x -> 2
返り値の型を宣言しない場合は、 型が違うと言われます。
fn two() { 2 } fn main() { let x = two(); println!("x -> {}", x); }
error[E0308]: mismatched types --> demo.rs:2:2 | 1 | fn two() { | - possibly return type missing here? 2 | 2 | ^ expected (), found integer | = note: expected type `()` found type `{integer}`
文末にセミコロンを使用した場合は、返り値の型が違うぞと言われます。
fn two() -> i32 { 2; } fn main() { let x = two(); println!("x -> {}", x); }
error[E0308]: mismatched types --> demo.rs:1:13 | 1 | fn two() -> i32 { | --- ^^^ expected i32, found () | | | implicitly returns `()` as its body has no tail or `return` expression 2 | 2; | - help: consider removing this semicolon | = note: expected type `i32` found type `()`
セミコロンに関しては、 return
の糖衣構文であるため、 return
をつけて上げると、実行可能です。
個人的には、 return
が無いほうがシンプルに書けるので、つけない方向で書いていきたいが、 return
を使わなければならないパターンがあるのだろうか・・・
fn two() -> i32 { return 2; } fn main() { let x = two(); println!("x -> {}", x); }
x -> 2