Rust 1.0の前に、この廃止されたクロージャ構文を使用して構造を書くことができました:
struct Foo {
pub foo: |usize| -> usize,
}
今私は次のようなことができます:
struct Foo<F: FnMut(usize) -> usize> {
pub foo: F,
}
しかし、私が作成するFoo
オブジェクトのタイプは何ですか?
let foo: Foo<???> = Foo { foo: |x| x + 1 };
参照を使用することもできます:
struct Foo<'a> {
pub foo: &'a mut FnMut(usize) -> usize,
}
これは遅いと思います
FnMut
のタイプに特化はありません_||
_構文を使用した古いスタイルのクロージャーは、スタックに格納されたクロージャーへの参照であり、&'a mut FnMut(usize) -> usize
と同等になりました。古いスタイルのproc
sはヒープに割り当てられ、Box<dyn FnOnce(usize) -> usize>
と同等でした(proc
を呼び出すことができるのは1回だけです)。
3番目のコードスニペットで使用するタイプについては、is n't one;があります。クロージャタイプは匿名であり、直接名前を付けることはできません。代わりに、次のように記述します。
_let foo = Foo { foo: |x| x + 1 };
_
needを使用してFoo
が必要であることを指定するコンテキストでコードを記述している場合は、次のように記述します。
_let foo: Foo<_> = Foo { foo: |x| x + 1 };
_
__
_は、実際のジェネリック型を推測するよう型システムに指示します。
降順で使用するwhichに関する一般的な経験則:
struct Foo<F: FnMut(usize) -> usize>
。これは最も効率的ですが、特定のFoo
インスタンスが格納できるのはoneクロージャのみであることを意味します。すべてのクロージャが異なる具象型を持っているためです。&'a mut dyn FnMut(usize) -> usize
。ポインターの間接指定がありますが、互換性のある呼び出しシグニチャーを持つ任意のクロージャーへの参照を保管できるようになりました。Box<dyn FnMut(usize) -> usize>
。これには、ヒープにクロージャを割り当てることが含まれますが、ライフタイムについて心配する必要はありません。参照と同様に、互換性のあるシグネチャを持つ任意のクロージャを保存できます。デモンストレーションのために、既存の回答をさらにいくつかのコードで補完します。
ジェネリック型を使用します。
struct Foo<F>
where
F: Fn(usize) -> usize,
{
pub foo: F,
}
fn main() {
let foo = Foo { foo: |a| a + 1 };
(foo.foo)(42);
}
struct Foo {
pub foo: Box<dyn Fn(usize) -> usize>,
}
fn main() {
let foo = Foo {
foo: Box::new(|a| a + 1),
};
(foo.foo)(42);
}
struct Foo<'a> {
pub foo: &'a dyn Fn(usize) -> usize,
}
fn main() {
let foo = Foo { foo: &|a| a + 1 };
(foo.foo)(42);
}
struct Foo {
pub foo: fn(usize) -> usize,
}
fn main() {
let foo = Foo { foo: |a| a + 1 };
(foo.foo)(42);
}
作成した
Foo
オブジェクトのタイプは何ですか?
これは、名前を付けることができない、自動的に生成されるタイプです。
参照を低速で使用することもできます[...]ポインタの逆参照[...]特殊化がないため
おそらく、しかしそれは発信者にとってはるかに簡単です。
以下も参照してください。