やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustの高度な機能(関数、クロージャ)

 関数ポインタ、クロージャの返却。

成果物

参考

関数ポインタ

fn add_one(x: i32) -> i32 {
    x + 1
}
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    f(arg) + f(arg)
}
fn main() {
    let answer = do_twice(add_one, 5);
    println!("The answer is: {}", answer);
}
$ rustc main.rs
$ ./main
The answer is: 12
fn main() {
    let list_of_numbers = vec![1, 2, 3];
    let list_of_strings: Vec<String> = list_of_numbers
        .iter()
        .map(|i| i.to_string())
//        .map(ToString::to_string)
        .collect();
}

 ToString::to_stringはフルパス記法。to_stringメソッドは複数あるため。

クロージャを返却する

fn returns_closure() -> Fn(i32) -> i32 {
    |x| x + 1
}
error[E0277]: the size for values of type `(dyn std::ops::Fn(i32) -> i32 + 'static)` cannot be known at compilation time
 --> main.rs:7:25
  |
7 | fn returns_closure() -> Fn(i32) -> i32 {
  |                         ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn(i32) -> i32 + 'static)`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: the return type of a function must have a statically known size

 エラー。コンパイラにはクロージャを格納するのに必要なメモリサイズがわからないため。そこでトレイトオブジェクトを使う。以下はコンパイル成功する。

fn returns_closure() -> Box<Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで