はじめに
前回は、「Tauri 2.0」と「Rust」についての基本情報と環境整備を解説しました。今回は、実際にお絵描きアプリを作る前に、まずRustの文法についておさらいしておきましょう。もしRustの文法をよくご存知なら、この回は読み飛ばしても大丈夫です。特別なことは書いていません。
ただしプログラミング言語「C/C++」を知っていても、Rustには所有権という独特なメモリ管理の概念があるので、Rustが初めての方は必ず読んでください。「new」や「delete」とは一味違います。
Rustの知っておくべき文法
プログラミング言語において、最も基本で最も重要な文法の1つが「変数」です。
変数には値を入れたり見たり後から値を上書きしたりすることができます。変数に入れられる値には「データ型」という種類が決められています。数値の変数は算数と同じ計算ができます。またプログラムの処理をまとめて「関数」にできます。
この連載では使わないので解説しませんが、「辞書型」という文法もあります。その名の通り辞書で単語を調べると単語の意味が分かるのに似ています。
変数
次のサンプルコードのように書くと上から順にプログラムが実行されてターミナルに"i=1975"という文字列が表示されます。「let」で「i」という変数に「1975」という数値を「=」で代入します。多くのプログラミング言語において「=」は「等号」ではなく「代入」を意味し「代入演算子」と言います。
「println!」は「マクロ」というもので、ここでは文字列をターミナルに表示する機能を持つものだと理解してください。""で囲まれた文字列がターミナルに表示されます。{}の部分にiの値が差し込まれます。
fn main() { let i = 1975; println!("i={}",i); }
データ型
データ型の種類の表を見る前に、次のサンプルコードを見てください。前のサンプルと違って「let b1:bool」と変数に「: bool」がついています。「bool」には「true」か「false」だけを代入でき、この型がデータ型です。
fn main() { let b1: bool = true; println!("b1={}",b1); let i1: i8 = 123; println!("i1={}",i1); let u1: u16 = 12345; println!("u1={}",u1); let i2: i32 = 1234567890; println!("i2={}",i2); let u2: u64 = 1234567890123456789; println!("u2={}",u2); let f1: f32 = 0.12345678; println!("f1={}",f1); let f2: f64 = 0.1234567890123456; println!("f2={}",f2); let s1: char = '字'; println!("s1={}",s1); let s2: &str = "文字列1"; println!("s2={}",s2); let s3: String = "文字列2".to_string(); println!("s3={}",s3); }
では、データ型の種類の表を見てください。「符号なし」というのは「正の整数」です。書いてはいませんが「符号あり」の整数は正負両方の整数です。
「f32」と「f64」は「浮動小数点」と言われますが、整数も含まれるので「実数」と説明しました。それぞれ使える数値の範囲が異なります。また必ず1文字の「char」型と、0〜複数文字列の「str」型があります。
データ型 | 説明 |
---|---|
bool型 | trueとfalseの真偽値 |
u8型 | 8bitの0~255の符号なし整数 |
u16型 | 16bitの0~65535の符号なし整数 |
u32型 | 32bitの0~4294967295の符号なし整数 |
u64型 | 64bitの0~18446744073709551615の符号なし整数 |
usize型 | 32bitと64bitの0~18446744073709551615の符号なし整数 |
i8型 | 8bitの-128~127の整数 |
i16型 | 16bitの-32768~32767の整数 |
i32型 | 32bitの-2147483648~2147483647の整数 |
i64型 | 64bitの-9223372036854775808~9223372036854775807の整数 |
isize型 | 32bitと64bitの-9223372036854775808~9223372036854775807の整数 |
f32型 | 32bitの-3.4028235e38~3.4028235e38の実数(「e」は「浮動小数点定数」) |
f64型 | 64bitの-1.7976931348623157e308~1.7976931348623157e308の実数 |
char型 | 1文字のユニコード文字 |
str型 | ユニコード文字列 |
演算子
次のサンプルコードのように基本的な計算は「加減乗除」と「剰余」だけです。剰余とは、除算した余りのことです。これらを組み合わせれば3DCGなどの複雑な計算もできてしまいます。
「加算」は「+」、「減算」は「-」、「乗算」は「*」、「除算」は「/」、「剰余」は「%」の記号で計算します。これらを「算術演算子」と言います。ほとんど算数そのままですね。数学も突き詰めればこれらの算数の計算だけでできるのと同じことです。
また加算と代入を同時にするには「+=」、減算と代入を同時にするには「-=」、乗算と代入を同時にするには「*=」、除算と代入を同時にするには「/=」、剰余と代入を同時にするには「%=」を使います。これらを「複合代入演算子」と言います。
fn main() { let i1 = 9 + 8; println!("i1={}",i1); let mut i2 = i1 - 7; // 後で値が変更されるので「mut」を付ける println!("i2={}",i2); let i3 = i2 * 6; println!("i3={}",i3); let i4 = i3 / 5; println!("i4={}",i4); let i5 = i4 % 4; println!("i5={}",i5); i2 += i3; println!("i2={}",i2); }
配列
次のサンプルコードのように複数の変数を1つにまとめて持てるものが「配列」です。配列は「let 配列名 = [値1,値2,]」と宣言し、「配列名[インデックス番号]」で値を代入したり値を見たりできます。
配列の文法
let mut 配列名 = [値1,値2,・・・];
配列名[インデックス番号] = 値3;
let 変数 = 配列名[インデックス番号];
今回は省略しますが、配列によく似た文法で「タプル」という文法があります。配列の要素は全て同じデータ型の変数を持たなければなりませんが、タプルは異なるデータ型の要素を持つことができます。
fn main() { let mut arr = ["鉛筆","ボールペン","万年筆"]; // 後で値が変更されるので「mut」を付ける println!("{}",arr[0]); println!("{}",arr[1]); arr[2] = "ガラスペン"; println!("{}",arr[2]); }
関数
説明が遅れましたが、「fn main()」は関数を宣言しています。main関数がプログラム起動時に最初に呼ばれ、それに続く{と}のスコープ内の処理を実行します。そして次のサンプルコードのようにmain関数以外にも関数を作ることができます。
ここでは「func」関数が宣言され、func(2024)が呼ばれると「hikisu」引数として2024が渡され、「format!」マクロで"と"内の文字列を「modoriti」変数に代入します。関数から値を返す値を「戻り値」と言います。modoriti戻り値は「return modoriti;」と書いても正しいです。ただ前者の方がコード量が少なくなる分、見た目がエレガントです。
関数の文法
fn 関数名(引数1: データ型,引数2: データ型,・・・) -> 戻り値 {
ステートメント
戻り値
}
fn main() { let s = func(2024); println!("{}",s); } fn func(hikisu:usize) -> String { let modoriti = format!("hikisu={}",hikisu); modoriti }