stringの限界 | Rust by Example
Rust Examplesより
map_errの引数は関数であるのにenumを直接ドーンと代入している箇所があって、どういうことか疑問に思ったので調べてみました。
現象
map_errの引数はFnOnce(E) -> Fであるのに関数の代わりにenumを渡してもきちんと処理されていた。
use std::num::ParseIntError;
use std::fmt;
type Result<T> = std::result::Result<T, DoubleError>;
enum DoubleError {
EmptyVec,
Parse(ParseIntError),
}
fn double_first(vec: Vec<&str>) -> Result<i32> {
vec.first()
.ok_or(DoubleError::EmptyVec)
.and_then(|s| s.parse::<i32>()
.map_err(DoubleError::Parse)
.map(|i| 2 * i))
}
検証
ドキュメントの型通りにmap_errを実装するなら
fn double_first(vec: Vec<&str>) -> Result<i32> {
vec.first()
.ok_or(DoubleError::EmptyVec)
.and_then(
|s| s.parse::<i32>()
.map_err(|e|DoubleError::Parse(e))
.map(|i| 2 * i)
)
}
になると思ったし、これで問題なく動きます。
enumのタプル構造体を渡してもどちらでも動くのでもしかしてmap_errだけでなく、他でも動作するのではと思い、以下サンプルを試してみました。
#[derive(Debug)]
enum Osaka {
Takoyaki(i32),
}
fn takoyaki<F>(f: F) where
F: FnOnce(i32) -> Osaka
{
println!("{:?}", f(7));
}
fn main() {
takoyaki(Osaka::Takoyaki);
}
できてしまいました・・・
検索すると出てきました
列挙型
以下抜粋
列挙型のコンストラクターは関数のようにも使うことができます
試しに意図的にエラーを起こして、エラーメッセージを読んでみます。
fn main() {
println!("{}", Osaka::Takoyaki);
}
すると型が判明し、fn(i32) -> Osakaだということがわかりました。
なんかこんなのもありました。
Rust 1.40.0でtuple構造体とenum variantのコンストラクタがconst fnになる - Qiita
感想
すっ飛ばそうと思ったけど、ちゃんと調べてよかった!スッキリ!