【Rust】がばがばRust独学 - 13. Functional Language Features - 1 Closures (2)
Rustの公式ドキュメントを通して、Rustを独学していく記事になります。(がば要素あり)
今回も、Functional Language FeaturesのClosuresについて学びつつ、気になった点をコード確認した結果を記事にしています。
- versions
$ rustc --version rustc 1.40.0 (73528e339 2019-12-16)
Closures: Anonymous Functions that Can Capture Their Environment
Closures: Anonymous Functions that Can Capture Their Environment - The Rust Programming Language
Closure Type Inference and Annotation
下記のClosureでは、パラメータに対する型や戻り値に対する型を利用していません。
let expensive_closure = |num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
下記のように、型をつけることも可能です。
let expensive_closure = |num: u32| -> u32 { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
しかし、通常はClosure自体は短く、狭いコンテキスト内で使用され、かつ関数内のクローズドな匿名関数であるため、型を推測できます。
そのため、型をつける冗長性を無くすために、一般的に型を記述しません。明示性・明確性を高めたい場合は型をつけてよいと記載されていました。
Fn
について
昨日の記事にも出てきた Cacher
内に使用されている Fn
についてです。
struct Cacher<T> where T: Fn(u32) -> u32 { calculation: T, value: Option<u32>, }
クロージャーの型として Fn
には3つ利用することが出来ます。
FnOnce
: Closureが変数の所有権を取得FnMut
: 可変な値のOwnerを借用Fn
: 不変な値のOwnerを借用
ドキュメントを読んでも分からない・・・
ってことで、まずは定義を確認する。
pub trait Fn<Args> : FnMut<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call(&self, args: Args) -> Self::Output; } pub trait FnMut<Args> : FnOnce<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } pub trait FnOnce<Args> { /// The returned type after the call operator is used. #[stable(feature = "fn_once_output", since = "1.12.0")] type Output; /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call_once(self, args: Args) -> Self::Output; }
違いとしては、下記になります。
FnOnce
:self
FnMut
:&mut self
Fn
:&self
上記から推測すると、 FnOnce
はClosureをそのまま利用するため1回利用・・・? Fn
はアドレス参照なので複数回利用?そして、 FnMut
はClosureを変更可能・・・?という風に読み取れますが、ちょっとわからないので、別記事に・・・
まとめ
- Closureには型定義を一般的には実施しない
- 明示性・明確性を高めたい場合は必要
FnOnce
、FnMut
、Fn
まじでわからん
最後に
Fn
系は今までに触ったことのない(もしくはよしなに頑張ってもらっていた?)概念なので正直分からない・・・
とりあえず、先に進めるために、次はIteratorsについて深めます。