コンテンツにスキップ

Rustの構文

Rustを動かせるようになったので、ここでひと息ついて、プログラムの各部分が実際に何を意味しているのかを見ていきましょう。いちばん小さな例を使って、ひとつずつ分解していきます。

fn main() {
println!("こんにちは、世界!");
}

実行結果:

こんにちは、世界!
▶ 実際に試してみよう
fn main() {
// ここに書いたコードが実行される
}

Rustのプログラムはすべて、main という名前の関数から始まります。プログラムを実行すると、Rustは main を探して、その中のコードを実行します。

  • fn は関数(名前の付いたコードのかたまり)を定義するためのキーワードです。
  • main は関数の名前です。この名前は特別で、プログラムの入り口(エントリーポイント)になります。
  • () には関数が受け取る入力が入ります(ここでは空です。main は何も受け取りません)。
  • { } の波かっこが、関数に属するコード、つまり本体を囲みます。

本体の中にある一つひとつの命令は、たいてい文(statement)です。文はセミコロン ; で終わります。

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

実行結果:

15
▶ 実際に試してみよう

必要な場所にセミコロンを書き忘れるのは、初心者がもっともよくやるミスのひとつです。でも心配はいりません。コンパイラがその場所をはっきり指摘してくれます。

Rustのコードは2種類の部品でできています。この違いは、ほとんどの言語よりもRustで大きな意味を持ちます。

  • 文(statement)は、何かをするけれど、値は返しません。let x = 5; は文です。
  • 式(expression)は、値を生み出します。5、x + 1、x * 2 はどれも式です。

多くの人が驚くのはここからです。波かっこ { } で囲んだコードのブロックも式なのです。ブロックの値は、セミコロンを付けずに書いた最後の行になります。

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // ブロックの中の文
doubled + 1 // セミコロンなし:これがブロックの値になる
};
println!("y は {y} です");
}

実行結果:

y は 11 です
▶ 実際に試してみよう

ブロックは中の文を実行し、そのあと doubled + 1、つまり 11 を返します。それが y になります。閉じかっこ } のあとにセミコロンがあることにも注目してください。let y = ...; の行全体は、やはり文なのです。

doubled + 1 のあとにセミコロンを付けると、それはブロックの値ではなくなります。するとブロックは「何もない」値(Rustでは () と書きます)を返し、println! はそれを表示できないので、コンパイルが通らなくなります。この「最後の行にはセミコロンを付けない」というルールは、まさに関数が値を返すしくみそのものです。関数のページや、式としての if でもまた出てきます。

println! をよく見てください。最後のビックリマークは打ち間違いではありません。! は、これが普通の関数ではなくマクロ(macro)であることを表しています。

マクロについて、今は完全に理解しなくて大丈夫です。覚えておいてほしいのはこれだけです。! が付いていたら、それはマクロです。今のところ使うのは、テキストを表示する println! だけです。

fn main() {
println!("これはマクロの呼び出しです");
}

println! の中にある波かっこ {} はプレースホルダーです。テキストのあとに渡した値が、ここに順番に埋め込まれます。

fn main() {
let name = "Ferris";
let age = 10;
println!("{}は{}歳です", name, age);
}

実行結果:

Ferrisは10歳です
▶ 実際に試してみよう

波かっこの中に変数名を直接書くこともできます。こちらのほうがすっきり読めることが多いです。

println!("{name}は{age}歳です");

RustはPythonのようにインデントを気にしません。ブロックの始まりと終わりは、波かっこ { } で判断します。インデントは、人間がコードを読みやすくするためのものです。

とはいえ、コミュニティには標準のスタイルがあり、Rustにはそれを自動で適用してくれるツールが付いています。

Terminal window
cargo fmt

cargo fmt を実行すると、コードが公式のスタイルに整形されます。使う習慣をつけておきましょう。

コードの中に、Rustが無視するメモを書いておくことができます。これをコメントと呼び、// で始めます。

fn main() {
// これはコメント。Rustは読み飛ばす
println!("こんにちは!"); // 行の最後にもコメントを書ける
}

コメントについては、次のページでもっと詳しく説明します。

a = 7 と b = 3 の2つの変数を作り、7 + 3 = 10 と表示してください。足し算はRustにやらせましょう。ヒント:println! には {} のプレースホルダーをいくつも書けます。テキストのあとに並べた値で、順番に埋められます。

解答を見る
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

実行結果:

7 + 3 = 10
▶ 実際に試してみよう

あるお店で、1個4円の商品を3個買い、送料が2円かかります。{ } のブロックを使って total を計算してください。ブロックの中で subtotal を作り、subtotal + 2 を返します。合計: 14 と表示しましょう。ヒント:ブロックの最後の行には、セミコロンを付けないでください。

解答を見る
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // 送料
};
println!("合計: {total}");
}

実行結果:

合計: 14
▶ 実際に試してみよう
  • プログラムはすべて main 関数から始まります。
  • コードは波かっこ { } の中に書き、ほとんどの文は ; で終わります。
  • 文は何かをし、式は値を生み出します。ブロックの最後の行に ; がなければ、それがブロックの値になります。
  • (println! のように)! が付いていたら、それはマクロです。
  • println! の中の {} は、渡した値で埋められるプレースホルダーです。
  • インデントは読みやすさのためのものです。cargo fmt で自動整形できます。

理解度チェック

1. Rustのプログラムで、main 関数の特別な点は何ですか?

2. println のあとに付いている ! は何を意味しますか?

3. let y = { let a = 2; a + 1 }; のあと、y の値はいくつですか?

スコア: 0 / 3