9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

main関数

Rustファイル(.rs)を実行する際はエントリーポイントとなるmain関数が必要です。

// ファイルの中にmainという関数が必要
fn main() {
  let msg = "Hello, world!";
  println!("{}", msg);
}

Cargoプロジェクトの場合、src/main.tsmain関数が無い状態でcargo runを実行すると以下のエラーメッセージが出ます。

error[E0601]: `main` function not found in crate `qiita_sample`

TypeScriptのファイルはどの関数からでも開始できます。

TypeScript
// 直に書いてもいいし・・・
const msg = "Hello, world!";
console.log(msg);

// 好きな関数名で定義してもいい
const hello = () => {
    const msg = "Hello, world!";
    console.log(msg);
}
hello();
# どちらにしてもファイル名だけ指定すれば動く
node index.ts

変数の宣言

変数の宣言はletで行います。この方法で宣言した変数はimmutable(不変)です。

let x = 5; // 不変の変数
println!("The value of x is: {}", x);

後から変数を変更したい場合はlet mutのようにmutを付与します。

let mut y = 5; // 可変の変数
println!("The initial value of y is: {}", y);
y = 10; // 値を変更
println!("The new value of y is: {}", y);

TypeScriptでいうletは可変性がある(再代入が可能)ことに注意してください。
また、TypeScriptではconstを使って宣言しても代入以外での変更自体は可能でした(例:配列の.push)。

const arr = [1, 2, 3];
arr.push(4); // 配列に値を追加
console.log(arr); // [1, 2, 3, 4]

Rustにおけるimmutableはそれも不可能になるので注意しましょう。Rustにおける不変性はメモリ内部の値そのものが不変であることを意味します。

Rustは静的型付け言語なので、各変数は型を持ちます。
基本的には型推論(宣言時の初期値から型を自動で割り当ててくれる)してくれますが、明示的に指定したい場合はlet <変数名>: <型名> = <初期値>;の形を取ります。

let z: i32 = 42; // 明示的に型を指定
println!("The value of z is: {}", z);

ここの書き味はTypeScript(を含めた他の静的型付け言語)と似ていますね。

Rustに用意されているいくつかの型を紹介します。

  • i8, i16, i32, i64, i128: 符号付き整数
  • u8, u16, u32, u64, u128: 符号なし整数
  • f32, f64: 浮動小数点数
  • bool: 真偽値
  • char: 文字
  • &str: 文字列スライス
  • String: 可変長の文字列

TypeScriptでは数値を扱う場合は単にnumberとすることがほとんどでしたが、Rustでは性能とメモリの効率を考慮してサイズを詳細に指定できます。

charは「文字」を表現するのであって、「文字列」を表現するのではないことに注意してください。文字列を表現したい場合は&strStringを使用します。

&str

文字列を表現するプリミティブ型になります。どこかしらの領域に存在する文字列へのポインタなので&がついています(Rustでは&をつけるとポインタになります)。厳密に言えば、これはUTF-8のスライス(後日の記事で解説)になります。そのため、参照先が変更されるとこちらも変更の影響を受けます。

fn main() {
    let greeting: &str = "Hello, world!";
    println!("{}", greeting);
}

String

&strが不変なスライス型であったのに対し、String型は文字列を格納するための可変な所有型であり、文字列の長さや内容を変更できます。Stringの中身はUTF-8のVecになります(後日の記事で解説)。Stringを生成する際は通常、String::fromメソッドやto_stringメソッドを使用します。

fn main() {
    let mut greeting = String::from("Hello");
    greeting.push_str(", world!"); // 文字列に追加
    println!("{}", greeting);
}

相互変換

&strStringは相互に型変換が可能です。

fn main() {
    let static_str: &str = "I'm a &str";
    let string_obj: String = String::from(static_str);

    let slice_from_string: &str = &string_obj;
    println!("{} and {}", string_obj, slice_from_string);
}

正直筆者はこのあたりの文字列の仕様を理解しきれていません。&strが厳密な文字列への参照なのに対し、Stringが柔軟な文字列型である、という認識程度です。
気をつけなければいけないのが、std::strstd::stringといった標準ライブラリが提供する関数が、元の文字列を操作したうえでオリジナルの参照を返すのか、新しくメモリ領域を確保して新しい参照を返すのかをきちんと把握するということです。

そう考えると、パフォーマンスはともかく無邪気にstringを使えていたTypeScriptは考えることが少なくてサクッと書けたなぁという感想です。

所有権やライフタイムについて

Rustの変数には「所有権」や「ライフタイム」といった独自の仕組みがあります。これらは(個人的には)非常にややこしいですが、こういう機構があるからこそ、Rustの高パフォーマンス性が実現できています(そのはず)。これらについてもこのアドベントカレンダーで順を追って取り上げていきます。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?