テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(rust report) クロージャの理解 (2)

Rustのクロージャは他の言語とは違う. GCがないからだ. クロージャは環境を食う. GCがある場合は食ったオブジェクトの参照カウントを増やせばいいが, Rustはそんなことはせずにそのクロージャがどういうクラスのものかを判定し, 型で分離する. そのクラスは「所有権を食ったか」「環境を書き換えるか」で決定される. オブジェクト一般に対して適用されるルールがクロージャにも適用されている. (まるでC++のconst汚染のようだ)

クロージャはこのように, 他の言語とは違い, Rust特有のあれこれについて理解を求められるため, 初心者にとって鬼門となる. Noobなおれが過去に書いたブログは以下:

(rust report) Rust docのクロージャ章を読んだのでおれの理解をまとめる - テストステ論

(rust report) クロージャが利用する環境のみをborrowしていることの証明 - テストステ論

今, Programming Rustを読んでいる. 12章はクロージャの章であり, 面白い図があったのでそれをシェアしたいというのと, おれ自身理解が深まったのでそれを書きまとめる目的でこの記事を書く.

Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

早速だがその図がこれ.

f:id:akiradeveloper529:20161227183037p:plain

“Fn is the family of closures and functions that you can call multiple times without restriction. This highest category also includes all fn functions. FnMut is the family of closures that can be called multiple times if the closure itself is declared mut. FnOnce is the family of closures that can be called once, if the caller owns the closure. Every Fn meets the requirements for FnMut, and every FnMut meets the requirements for FnOnce. As shown in Figure 12-2, they’re not three separate categories.”

(抜粋:: Jim Blandy and Jason Orendorff “Programming Rust”。 iBooks)

ルールは

  1. そのクロージャがdropをするならば (Closure that kills), そいつはFnOnceとなる
  2. そのクロージャが環境を書き換えるならば, FnMutとなる
  3. それ以外はFnとなる

クロージャはデフォルトで環境を「参照」する. 従ってふつうはFnになる. このクラス分けは, Rustコンパイラによって自動に行われる.

ではmoveクロージャはどうか?

これは答えが書いてある.

By-value closures automatically implement this trait, which allows them to be invoked.

(https://doc.rust-lang.org/std/ops/trait.FnOnce.html)

moveをつけるとクロージャはデフォルトの参照キャプチャではなく所有権の移動をする. そのようなクロージャを2度呼ぶことは明らかに許されないので, FnOnceというのは自然だ.

Rustはいつdropするのかについてはもう少し詳しく分かったらまとめようと思う.

Rustは日本でも興味を持ってる人が増えては来ているが多くは, 言語に興味がある人である. HaskellとかOCamlがもともと書けて, その延長でRustに言語的に興味を持っている. 一方おれは応用に興味がある. Rustで価値のある基盤ソフトウェアを作りたいと思っている. そういう人は海外では増えているけど, IT後進国の日本ではまだあまり多くない. ブログを通じて少しずつ増やしていければいいと思って書いている.