🦀

Rustで少し複雑なClosureをVecにpushする

2022/09/24に公開

はじめに

VecにClosureをpushしたいとする。簡単なClosureならさほど難しくない。

type Stack = Vec<fn(i8) -> i8>;

type World = (i8, Stack);

fn g(world: World) -> Stack {
    let (_, mut stack) = world;
    let f = |x: i8| x;
    stack.push(f);
    stack
}

少し複雑なパターン

  • 引数と戻り値にlifetime注釈が絡んでくる
  • ローカル変数を使用する

なケース

struct A<'a> {
    first: &'a str,
    second: i8
}

type Stack<'a> = Vec<Box<dyn Fn(A<'a>) -> A<'a>>>;

type World<'a> = (i8, Stack<'a>);

fn infer_lifetime<'a, T: 'a, F: Fn(T) -> T>(f: F) -> F {
    f
}

fn g(world: World) -> Stack {
    let (_, mut stack) = world;
    let a = 0;
    let f = infer_lifetime(move |x: A| A{first: x.first, second: a});
    stack.push(Box::new(f));
    stack
}
  • lifetime注釈をつける
  • fnではなくBox<dyn Fn>にする
  • infer_lifetimeでClosureを包む

がKey。

参考
https://stackoverflow.com/questions/63843906/why-can-i-not-return-a-reference-from-a-closure

Discussion