Haskellのカリー化された部分適用できるような関数Rustでも書けるかな~(^-^)/言うて書いた結果なんですけれども、
#![feature(type_alias_impl_trait)]
type Fnu32 = impl Fn(u32) -> u32;
type FnFnu32 = impl Fn(u32) -> Fnu32;
const A: FnFnu32 = add_triple(33);
fn main() {
let a = A(4);
let b = a(8);
let c = a(13);
println!("{} {}", b, c);
}
const fn add_triple(a: u32) -> FnFnu32 {
let add_double = move |b: u32| -> Fnu32 {
let add_single = move |c: u32| -> u32 { a + b + c };
add_single
};
add_double
}
これがなぜか成功する。 ちなみに返り値にimpl Traitができるようにするため、次の記事を参考にした:対処法: Rustの高階関数の関数ポインタの戻り値型にimpl Traitを使えるようにする(Nightly)
部分適用する関数が作れたことにまず驚いたが、それがconst fn
にすることまでできるとは思わなかった。
メモリ構造どうなってんの
あとFnトレイトだと使いまわせたが、FnOnceトレイトだと使いまわせなかった。そこら辺がよく分からない。あとFnトレイトでもmove
キーワードが必要だとコンパイラに指摘されて言われるがままに付けたが、なんで必要なのかもよく分かっていない。なんで?
と思ったので今コンパイルエラーを見た。
error[E0373]: closure may outlive the current function, but it borrows `b`, which is owned by the current function
--> src\main.rs:16:26
|
16 | let add_single = |c: u32| -> u32 { a + b + c };
| ^^^^^^^^^^^^^^^ - `b` is borrowed here
| |
| may outlive borrowed value `b`
|
note: closure is returned here
--> src\main.rs:17:9
|
17 | add_single
| ^^^^^^^^^^
help: to force the closure to take ownership of `b` (and any other referenced variables), use the `move` keyword
|
16 | let add_single = move |c: u32| -> u32 { a + b + c };
| ++++
error[E0700]: hidden type for `Fnu32` captures lifetime that does not appear in bounds
--> src\main.rs:17:9
|
3 | type Fnu32 = impl FnOnce(u32) -> u32;
| ----------------------- opaque type defined here
...
17 | add_single
| ^^^^^^^^^^
|
= note: hidden type `[closure@src\main.rs:16:26: 16:41]` captures lifetime `'_`
// 以下`a is borrowed here`についても同様
E0373とE0700らしい。 関数を返すんだからそりゃaとbがmove無しクロージャのせいで参照になってていつ死ぬか分からない、ということでコンパイルエラーを出したのはよく分かった。
E0700、あなたimpl Trait特有の話なのでよく分かりません…E0700だけ対処するとしてどうライフタイムパラメータを付ければいいか皆目見当がつきません…;;
You must log in or # to comment.