🦊
Rust で trait のエイリアス
名前が長すぎる trait を短くしたい
Rustを使っているときに、
Fn(i64, MyType<T>, bool, usize) -> (MyType<T>,i64)
みたいな長いtraitを何度も使いたく、traitの別名を作りたかったんですが、結構悩んだのでメモとして残しておきます。
クロージャを関数の返り値を
fn some_fn() -> impl Fn(i64, MyType<T>, bool, usize) -> (MyType<T>, i64)
{
|/* 省略 */| {/* 省略 */}
}
ではなく
fn some_fn() -> impl LongFn<T> {
|/* 省略 */| {/* 省略 */}
}
みたいに書きたかったので。
型のエイリアスは
type NanoSecond = u64;
のように簡単に書けるのですが、traitは調べてもなかなかわかりませんでした。また、上の例の場合、関数/クロージャごとに型が変わってしまうため、型のエイリアスを作ってもうまく行きませんでした。dynを含めた型は型エイリアスにすることはできません。
traitのエイリアスを作る
結論から言うと、次のようにやります。
trait LongFn<T>:
Fn(i64, MyType<T>, bool, usize) -> (MyType<T>, i64) {}
impl <S, T> LongFn<T> for S where
S: Fn(i64, MyType<T>, bool, usize) -> (MyType<T>, i64) {}
ジェネリックでtraitを実装することで、クロージャに自動的にLongFn<T>
が実装されて使うことができます (こんな書き方できるんだ...)。このようにすることで、traitのエイリアスを作ることができます。
ちなみにRust Unstableだと
trait_alias - The Rust Unstable Bookにあるように、次のようなtraitのエイリアスが提案されていました。
上のような方法があるので、今後安定化される可能性は低いでしょう。
#![feature(trait_alias)]
trait Foo = std::fmt::Debug + Send;
trait Bar = Foo + Sync;
参考
Discussion
こちらの記事では、マクロを使う方法を紹介されていました。マクロを型の位置で使うという記事自体が珍しいと思うので、ご参考までに貼らせていただきます。