Rustは、高いパフォーマンスとメモリ安全性を両立させるプログラミング言語として、2026年現在も多くの開発現場で採用されています。
システム開発からWebアプリケーションのバックエンドまで、幅広い用途で利用されるRustを習得する上で、まず避けては通れないのが「関数」の定義と活用です。
Rustの関数は、他のプログラミング言語と似た部分も多いですが、静的型付けや所有権といったRust独自の概念が密接に関わっています。
本記事では、Rustにおける関数の作り方について、基本構文から引数、戻り値の指定方法まで詳しく紹介します。
これからRustを学び始める方や、基本を再確認したい方は、ぜひ参考にしてください。
Rustにおける関数の基礎
Rustにおいて、関数はプログラムを構成する最小の実行単位です。
すべてのRustプログラムには、実行の起点となるmain関数が存在します。
fn main() {
println!("Hello, Rust!");
}
Hello, Rust!
関数を定義する際は、fnキーワードを使用するのが基本です。
Rustでは、関数の名前にはスネークケース(snake_case)を用いるのが慣例となっています。
スネークケースとは、すべての文字を小文字にし、単語の間をアンダースコアで繋ぐ形式のことです。
例えば、calculate_total_price や fetch_user_data といった名前が推奨されます。
関数の定義場所と呼び出し
Rustの大きな特徴として、関数の定義場所が呼び出し元よりも前であっても後ろであっても問題ないという点があります。
コンパイラがプログラム全体をスキャンするため、C言語のような前方宣言は必要ありません。
これにより、ロジックの重要度順にコードを並べることができ、可読性の高い構成を実現できます。
基本的な関数の定義方法
まずは、引数も戻り値も持たない最もシンプルな関数を作成してみましょう。
以下の例では、メッセージを表示するだけの say_hello 関数を定義しています。
fn main() {
// 関数の呼び出し
say_hello();
}
// 関数の定義
fn say_hello() {
println!("こんにちは、Rustの世界へ!");
}
こんにちは、Rustの世界へ!
関数名の後には必ず () (かっこ)を付け、その後に {} (波括弧)で関数本体を記述します。
呼び出し側でも、関数名の後ろに () を付けることで実行されます。
引数を持つ関数の作り方
関数にデータを受け渡すためには、引数を設定します。
Rustは静的型付け言語であるため、引数には必ず型注釈が必要です。
型を明示することで、コンパイラはコードの安全性を静的にチェックできます。
単一の引数を受け取る
引数を一つ受け取る関数の例を見てみましょう。
fn main() {
print_number(10);
}
// 引数xはi32型(32ビット整数)
fn print_number(x: i32) {
println!("受け取った数値は {} です。", x);
}
受け取った数値は 10 です。
引数名の後に : (コロン)を書き、その後に型を指定します。
もし型を省略した場合、Rustのコンパイラはエラーを出力し、ビルドを中断します。
複数の引数を受け取る
複数の引数を持たせる場合は、カンマ , で区切って定義します。
fn main() {
print_sum(5, 7);
}
fn print_sum(a: i32, b: i32) {
let sum = a + b;
println!("{} と {} の合計は {} です。", a, b, sum);
}
5 と 7 の合計は 12 です。
引数ごとに型を指定する必要があるため、a, b: i32 のような省略記法は使えない点に注意してください。
戻り値(返り値)の設定方法
関数から値を返したい場合は、引数リストの後に -> (矢印)を使って戻り値の型を指定します。
Rustの戻り値には、returnキーワードを使う方法と、文末の式を利用する方法の2種類があります。
式(Expression)による暗黙の戻り値
Rustでは、関数の最後にセミコロンを付けない「式」を記述することで、その値を戻り値として返せます。
これはRustで最も一般的な書き方であり、コードを簡潔に保つのに役立ちます。
fn main() {
let result = add(10, 20);
println!("計算結果: {}", result);
}
// 戻り値の型を i32 に指定
fn add(x: i32, y: i32) -> i32 {
x + y // セミコロンがない点に注目
}
計算結果: 30
式(Expression)は値を評価して返すのに対し、セミコロンが付いた「文(Statement)」は値を返しません。
もし x + y; と書いてしまうと、戻り値が空のタプル () とみなされ、型不一致のエラーが発生します。
returnキーワードによる明示的な戻り値
関数の途中で処理を終了して値を返したい場合は、return キーワードを使用します。
fn check_value(x: i32) -> String {
if x > 100 {
return String::from("大きすぎます"); // 早期リターン
}
String::from("正常な範囲内です")
}
早期リターンの場合は return を使い、関数の最後では式を用いるのがRustらしい綺麗なコードの書き方です。
所有権と参照の扱い
Rustの関数を使いこなす上で避けて通れないのが所有権の概念です。
引数として値を渡すと、その値の所有権が関数に移動(ムーブ)することがあります。
所有権の移動(ムーブ)
String 型などのデータを関数に渡すと、呼び出し元の変数は使えなくなります。
fn main() {
let s = String::from("hello");
take_ownership(s);
// println!("{}", s); // ここでsを使うとエラーになる
}
fn take_ownership(text: String) {
println!("所有権を受け取りました: {}", text);
}
参照渡し(借用)
所有権を移動させずにデータを使いたい場合は、参照(&)を渡します。
これを「借用」と呼びます。
fn main() {
let s = String::from("hello");
calculate_length(&s); // 参照を渡す
println!("元の文字列 '{}' はまだ使用可能です。", s);
}
fn calculate_length(text: &String) {
println!("文字列の長さは {} です。", text.len());
}
実務では、単にデータを読み取るだけの関数であれば、参照を使用するのが一般的です。
可変な参照の渡し方
関数内で引数の値を書き換えたい場合は、可変な参照 &mut を使用します。
fn main() {
let mut count = 10;
add_one(&mut count);
println!("更新後の値: {}", count);
}
fn add_one(num: &mut i32) {
*num += 1; // デリファレンスして値を書き換え
}
更新後の値: 11
&mut を使うことで、安全にデータを共有しながら変更を加えることができます。
Rust関数の高度な機能
より実用的なプログラムでは、エラー処理や汎用的なコードが求められます。
Option型やResult型を戻り値にする
Rustには例外処理がありません。
代わりに、失敗する可能性がある関数では Option<t></t> や Result<t, e=""></t,> を戻り値に設定します。
fn divide(numerator: f64, denominator: f64) -> Result<f64, string=""> {
if denominator == 0.0 {
Err(String::from("0で割ることはできません"))
} else {
Ok(numerator / denominator)
}
}
</f64,>
このように戻り値を設計することで、呼び出し側に適切なエラーハンドリングを強制でき、堅牢なアプリ開発が可能になります。
ジェネリック関数
異なるデータ型に対して同じロジックを適用したい場合、ジェネリクスを使用します。
fn print_anything<t: std::fmt::display="">(item: T) {
println!("表示: {}", item);
}
</t:>
<t></t> は型パラメータであり、呼び出し時に具体的な型が決まります。
関数作成におけるベストプラクティス
Rustで美しいコードを書くためのポイントをいくつか挙げます。
| 項目 | 内容 |
|---|---|
| 命名規則 | 常にスネークケース(snake_case)を使用する。 |
| 引数の型 | 具体的な型よりも、スライス(&str)やトレイト境界を活用する。 |
| 戻り値 | 可能な限り「式」による暗黙の戻り値を利用する。 |
| ドキュメント | /// を使って関数の説明や使用例(Example)を記述する。 |
特に String ではなく &str を引数に使うことで、文字列リテラルと String 型の両方を受け取れるようになり、関数の汎用性が高まります。
まとめ
Rustの関数は、一見すると他の言語と同じように見えますが、その背後には厳格な型チェックと所有権システムが存在します。
fnキーワードによる定義、型注釈の必須化、そして式による戻り値の記述方法は、Rustプログラミングの根幹を成す要素です。
まずはシンプルな引数と戻り値の扱いに慣れ、そこから参照や借用といったRust独自の概念へと理解を深めていくのが上達の近道です。
適切な関数の作り方をマスターすることで、2026年のモダンな開発シーンにおいても、安全で効率的なコードを記述できるようになります。
今回紹介した基本を土台にして、さらに高度なクロージャや関数ポインタの学習にも挑戦してみてください。
