冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

Rustの勉強(その9)

ちょっと間が空いてしまいました。妻が入院していて勉強どころではなかったので^^;

mao-instantlife.hatenablog.com

というわけで前回の続きです。

関数の続き

Diverging Function(発散関数?)

返ってこない関数のための特殊なシンタックスを言うらしいです。Javaで例外投げるイメージが一番近い。

fn diverges() -> ! {
panic!("This function is never return!"); // カレントスレッドをエラーでクラッシュさせる
}

Rustでは、上記の例の時に戻り値に指定している !diverges と呼んでいるとのこと。 RUST_BACKTRACE=1 で実行するとより正確なスタックトレースが出ます。

Diverging functionは各型にバインド可能らしいのですが、いまいちどういう用途か把握しかねております。とりあえずの先行実装とかですかね?

関数ポインタ

とりあえずありました。関数を変数にバインドできます。構文はScalaとかに似ててとっつきやすいです。

fn add_one(x: i32) -> i32 {
x + 1
}

let f: fn(i32) -> i32 = add_one; // 関数名のみ

f(1); // 2がリターンされる

上記は変数の型を省略して書くことが可能です。

ちなみに、部分適用ができるかどうかは書かれていませんでした。試しにScalaと同じプレースホルダーでできないか試してみたんですが、コンパイルエラーになります。プレイスホルダーについての説明が、本当にないのでできるかどうかもまだ確認できていません。まあ、最悪部分適用した関数を作ってそれをポインタにすればいいのではないかとも思いますが。

プリミティブ型

大まかにRustで扱うプリミティブ型は以下の通りです。

  • Boolean
  • 文字(char)
  • 数値
  • 配列
  • スライス?
  • 文字列
  • タプル
  • 関数

配列

配列はサイズ固定で要素はすべて同じ型であることが前提です。Rustはデフォルトで変数はimmutableなので、 mut を明示的につけないと要素の変更ができません。

配列の型表記は [T; N] で、 T は要素の型、 N は要素の数です。配列の初期化も似た様な書き方になります。

let nums = [0; 20];

println!("second value is {}", nums[1]); // 要素はインデックスでアクセス。0スタート
println!("nums length is {}", nums.len()); // 配列の長さを取得

20個の要素を持つ配列を宣言。型は初期値の0から推論されて i32 となります。

スライス

データ参照のための構造で、サンプルが配列しかないので、配列の部分を得るために使うものという理解をしました。直接値をバインディングしないのでメモリの節約になる、ということらしいです。フィルタリングするときにはスライスを使った方が良さそう、ということですね。

let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // すべての要素
let middle = &a[1..4]; // aから 1, 2, 3 をスライス

&[] でスライスを定義します。

タプル

シンタックス含めてだいたいScalaと同じ感じです。タプルの要素にはインデックスのメソッドでアクセス可能です。

タプルを使ってこんな感じの変数宣言もできます。

let (x, y, z) = (1, 2, 3);

println!("x is {}", x); // 各要素を変数として扱える

思ったより忘れてなかった

以下次号。