🐥

Rust で関数いろんなところで使おうとして困った話

2021/04/20に公開

なんというか、あらかじめ関数を登録して、それを何処かで呼び出すみたいな考えたりしなかったり。
悩んだこととか書こうと思ったのですが、まとめるのが苦手なダメ人間なので・・・・・

なんとなく作ってみたもの

Rust初心者の私が試行錯誤して作ってみたもの

struct Sample<'a> {
    func_list: HashMap<String, Box<dyn Fn(i32) -> i32 + 'a>>
}

impl<'a> Sample<'a> {
    fn new() -> Self{
        Self {
            func_list: HashMap::new()
        }
    }

    fn set_func(mut self, key: impl Into<String>, func: impl Fn(i32) -> i32 + 'a) -> Self {
        self.func_list.insert(key.into(), Box::new(func));

        self
    }
}

これでコンパイルエラーは出ない。

ところで dyn と impl の違いがいまいちわかってない

ドキュメントちゃんと読んでってことなんでしょうね_| ̄|○
ネットの海で適当に見ていると 動的ディスパッチ静的ディスパッチ の違いっぽいですね。

ということは積極的に使うべきはimplでそれでもだめな所でdynを適用していけばよいのでしょうか。。。。
dynを使うと コンパイル時にサイズが~ 見たいなエラーが出たりするので、dyn使うときはBoxを使うことが多いのかなと思っています。

こんな方法も

struct Sample<'a> {
    func_list: HashMap<String, &'a dyn Fn(i32) -> i32>
}

impl<'a> Sample<'a> {
    fn new() -> Self{
        Self {
            func_list: HashMap::new()
        }
    }

    fn set_func(mut self, key: impl Into<String>, func: &'a impl Fn(i32) -> i32) -> Self {
        self.func_list.insert(key.into(), func);

        self
    }
}

どうせ、 'a のライフタイムの指定をするのだからそもそも借用したのを保存すればよいのかなと思ったり。

しかしこのケースの場合呼び出し側が

sample.set_func("test", &|x| x );

& の一文字入れるのが微妙に好きになれない・・・・

どういった形の実装がいいのか悩みます。

Discussion