Rustプログラミングを始めよう

Rustプログラミングです。 超入門向け。

更新: 2022.7.23

Rustの公式サイト

参考ドキュメント、リファレンス、例題などがたくさんあります。

Rustの公式サイト : https://www.rust-lang.org/ja

目次

ソースのコンパイル

rustcコマンドで Rust で書かれたソースファイルをコンパイルできます。
Rust のソースファイルの拡張子は .rs を付けます。

  $  rustc  main.rs

コンパイルに成功すると、main という実行可能バイナリファイルが生成されるでしょう。
出来上がったプログラムを実行するには通常通り実行します。

  $  ./main

Hello,world!

はろーわーるど!
伝統的に、まず、これを作らなければプログラミングを始めることはできないと言われています。
プログラミング世界でのあいさつのようなものです。
これは画面に1行のメッセージ「Hello,world!」を表示するだけの最も簡単なものです。
Rust でこれをするには以下のようになります。

fn main() {
    println!("Hello,world!");
}

これを実行すればあいさつ完了です。

数値を表示する

「Hello,world!」プログラムにおいて println!(...) という部分が文字を出力している部分になります。
これを使って数字を出力するにはどうしたらよいのか?
次のコードを見てください。

fn main() {
    println!("数は {} です。", 500);
}

これを実行した結果は次のとおりです。

数は 500 です。

println!() の中の文字列にある {} の部分が、数字の 500 に置き換わります。
このようにメッセージ中にデータを埋め込むには {} という指定子を使います。
ここでは数値の 500 がセットされているため、500 に置き換わりました。

それでは、この {} が複数あるとどうなるのか?

fn main() {
    println!("{}  {}  {}", 10, 20, 30);
}

これを実行すると、

10  20  30

というように順番に出力されていることが分かります。

計算する

数値が表示できたので、今度はコンピュータに簡単な計算をさせてみることにします。
Rust も数値計算の方法は、いたって普通です。
足し算、引き算、掛け算、割り算ができます。
それぞれの、演算記号は + - * / です。

足し算と引き算:

fn main() {
    println!("{}", 15 + 22);
    println!("{}", 60 - 45);
}

掛け算と割り算:

fn main() {
    println!("{}", 18 * 42);
    println!("{}", 120 / 6);
}

割り算の余り、演算記号は % を使います:

fn main() {
    println!("{}", 125 % 30);
}

数式では括弧 ()も使えます。 ちょっと複雑な計算式:

fn main() {
    println!("{}", 3 * (9 - 5) + 20 / 4);
}

変数

変数は宣言してからでないと使用できません。 変数を宣言してみましょう。

    let x = 10;

これで、変数 x を宣言し、x に数値の 10 を代入したことになります。

変数の宣言と、データの代入は別々に行ってもかまいません。

    let x;

    x = 10;

しかし、Rustには特有の規則があります。
それは、通常の変数は「不変変数」というもので、
一度、値を代入すると、その値を変更することができません。
なので、変数に2回代入を行うとコンパイル時にエラーとなってはじかれます。

    let x = 10;

    x = 25;  // エラー! これはできない。

変数を使ったサンプルを書いてみましょう:

fn main() {
    let x = 150;

    println!("{}", x);
}

これを実行すると、画面に 150 と表示されるでしょう。

実は println! マクロでは、文字列中の出力フォーマットに変数名を
直接書き、その変数の値を出力することもできます。 このように:

fn main() {
    let x = 150;

    println!("{x}");
}

可変変数

Rustの変数は基本的に、一度代入すると、あとから変更することができませんが、
可変変数として宣言される変数には何度でも代入できます。
可変変数を宣言するにはキーワード mut をつけます。

fn main() {
    let mut x = 5;
    println!("{x}");
    x = 10;
    println!("{x}");
    x = 15;
    println!("{x}");
    x = 20;
    println!("{x}");
}

「可変」を意味する単語は "mutable" であることから、キーワードが mut なのでしょう。
ちなみに、「不変」を意味する単語は "immutable" です。

様々なデータと型注釈

データには様々なものがあります。
整数、小数、ブール値、文字と文字列などで、
変数に代入したり、操作したり、println! で表示したり
することができます。

    let i = 100;       // 整数
    let f = 1.25;      // 小数
    let b = true;      // ブール値
    let c = 'A';       // 文字
    let s = "hello.";  // 文字列

データには様々なものがありますが、
Rustプログラミング言語は、データ型の無い言語ではなく、
型に厳密な言語です。
しかし、変数のデータ型は、型推論によって
自動的に決定されるのでデータ型を指定しなくてもよいのです。

ただし、変数のデータ型をプログラマーが指定することも可能であり、
宣言した変数名の後ろに型注釈を付けることでデータ型を指定します。

    let i: i32 = 100;

上の例では、変数名の後ろにコロン(:)と、
そして i32 というものを付けています。
i32 というのがデータ型名であり、32ビット整数のデータ型です。

Rustのデータ型には次のようなものがあります。

データ型名データ
i8符号付き8ビット整数
i16符号付き16ビット整数
i32符号付き32ビット整数
i64符号付き64ビット整数
i128符号付き128ビット整数
u8符号なし8ビット整数
u16符号なし16ビット整数
u32符号なし32ビット整数
u64符号なし64ビット整数
u128符号なし128ビット整数
f3232ビット浮動小数点数
f6464ビット浮動小数点数
boolブール値
char文字

ちなみに、文字列に対しては &str という型名で型注釈を付けます。

    let s: &str = "hello.";

定数

const文を使って定数を定義することも可能です。

const NUMBER: i32 = 12345;

定数は大文字で書くことが一般のルールになっていますので、
大文字で書くのがよいでしょう。
また、定数は型注釈を書かなければならないことに注意してください。

const NUM: i32 = 50;

fn main() {
    let x = 2 * (NUM + 10);

    println!("{}", x);
}

if条件分岐

条件分岐は、もちろん if 文を使います。

fn main() {
    let x = 10;
    let mut y = -1;

    if x == 10 {
        y = 2;
    }

    println!("{y}");
}

else 文を使えば、条件が成立しなかったときにも対応できます。

fn main() {
    let x = 12;
    let y;

    if x == 10 {
        y = 2;
    } else {
        y = -1;
    }

    println!("{y}");
}

else if で、はしごすれば、複数の条件に対応することも可能です。

fn main() {
    let x = 20;
    let y;

    if x == 10 {
        y = 2;
    } else if x == 20 {
        y = 3;
    } else if x == 30 {
        y = 4;
    } else {
        y = -1;
    }

    println!("{y}");
}

whileループ

whileループによって、ブロック内のコードを繰り返し処理することが可能です。

試しに、ループ処理で1~100までの和を計算してみます。

fn main() {
    let mut i;
    let mut sum;

    sum = 0;
    i = 1;

    while i <= 100 {
        sum += i;
        i += 1;
    }

    println!("{sum}");
}

このプログラムを実行すると、「5050」と画面に表示されるでしょう。

上記のコードの += は、C/C++言語と同様に、
左の変数に右の式の値を加えることを意味します。

配列

配列を扱うには、大括弧 [ ] を使い、その中に要素を並べます。

fn main() {
    let a = [1, 2, 3, 4, 5];

    println!("{a:?}");
}

実行結果:

[1, 2, 3, 4, 5]

このプログラムでは、println!の出力に {a:?} というものが
指定されていますが、これは配列 a のデータを出力になります。
変数名の a のあとに :? を付ける必要があるので注意してください。
フォーマット指定で :? が付いているものは、
配列などの様々な種類のデータ出力に対応できるので便利です。

もちろん、配列の要素に1つずつアクセスすることも可能です。
配列変数の後ろに大括弧 [ ] を付けて要素番号を指定します。

fn main() {
    let a = [1, 2, 3, 4, 5];

    println!("{}", a[0]);
    println!("{}", a[1]);
    println!("{}", a[2]);
    println!("{}", a[3]);
    println!("{}", a[4]);
}

配列の要素番号は、0 から始まるので注意してください。

タプル

配列と似たようなものにタプルという、複数の要素を持つことができるデータ構造があります。
配列との違いは、配列がすべて同じデータ型の要素しか持つことができないのに対して、
タプルは異なるデータ型の要素を持つことができます。

配列のときと似ていますが、タプルでは要素を丸括弧 ( ) で括り並べます。

    let t = (1, 'A', 3.14, "hello.");

タプルを使う:

fn main() {
    let t = (1, 'A', 3.14, "hello.");

    println!("{t:?}");
}

実行結果:

(1, 'A', 3.14, "hello.")

配列と同様に、フォーマット指定で :? を使えば、タプルも直接表示できます。

タプルの要素へのアクセスは、配列と同じではありません。
次のようにします。

fn main() {
    let t = (1, 'A', 3.14, "hello.");

    println!("{}", t.0);
    println!("{}", t.1);
    println!("{}", t.2);
    println!("{}", t.3);
}

この例のように、変数のあとにドット . と要素番号を付けて指定します。

forループ

ループ処理の1つとして、for文があります。
これは、反復子(イテレータ)というものを指定して反復処理を繰り返すものです。
配列もイテレータとして指定することができ、
配列に for文で反復処理を行うと、配列の要素の先頭から最後まで、
1つずつ要素を取り出してブロックを処理します。

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut sum = 0;

    for n in a {
        sum += n;
    }

    println!("{sum}");
}

このプログラムを実行すると、結果は 150 になります。

このプログラムは、配列 a の要素を1つずつ取り出して、
変数 sum に合計値を加算します。

for文は、

for ループ変数 in イテレータ {
    .....
}

というような構造になっています。
イテレータから得られたデータを、
毎回、ループ変数に格納して処理を繰り返します。