iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
自我挑戰組

30 天快快樂樂學 Rust 系列 第 19

Rust 的閉包

  • 分享至 

  • xImage
  •  

什麼是閉包(closure)?

Rust 的閉包是一種匿名函式,可以從其函式的作用域中捕獲數值,而且閉包是為了快速執行而設計的,也因為如此它們的性能比一般函式還要好。

閉包有以下幾個特性:

  • 是一種匿名函式
  • 可以保存為變數,或是作為參數傳遞給其他函式
  • 可以在某處建立閉包,然後在不同的地方執行它
  • 可以從定義的作用域中捕獲變數

如何建立閉包?

閉包的建立方式:

  1. 使用 | 來分隔參數,| 後面是函式的主體
  2. 使用 {} 來包裹函式的主體

例如:

let plus_one = |x: i32| -> i32 { x + 1 };
plus_one(1); // 2

建立閉包的時候,有些特殊的地方可以注意:

  • 可以不用參數,直接使用 || 來建立一個空閉包
  • 可以不用 return 來回傳值,直接使用 -> 來指定回傳值的型別
  • 可以不用指定型別,Rust 會自動推導型別

如何使用閉包?

上面的範例中,我們建立了一個閉包,並且將它存到變數 plus_one 中,然後呼叫它。

閉包可以像函式一樣使用,例如:

fn main() {
    let plus_one = |x: i32| -> i32 { x + 1 };
    let a = plus_one(1);
    println!("a is {}", a); // a is 2
}

如何傳遞閉包?

閉包可以像函式一樣傳遞給其他函式,例如:

fn main() {
    let plus_one = |x: i32| -> i32 { x + 1 };
    let a = do_twice(plus_one, 1);
    println!("a is {}", a); // a is 3
}

fn do_twice<F>(f: F, arg: i32) -> i32
where
    F: Fn(i32) -> i32,
{
    f(arg) + f(arg)
}

上面的範例中,我們定義了一個函式 do_twice,它接受一個函式 f 和一個參數 arg,然後呼叫 f 兩次,並且將結果相加。

在呼叫 do_twice 的時候,我們傳遞了一個閉包 plus_one,並且傳遞了一個參數 1

如何捕獲變數?

閉包可以從定義的作用域中捕獲變數,例如:

fn main() {
    let num = 5;
    let plus_num = |x: i32| -> i32 { x + num };
    let a = plus_num(1);
    println!("a is {}", a); // a is 6
}

上面的範例中,我們定義了一個變數 num,並且將它傳遞給一個閉包 plus_num,然後呼叫 plus_num

在呼叫 plus_num 的時候,閉包會從定義的作用域中捕獲變數 num,並且將它加到 x 上。

如何使用 move 關鍵字來捕獲變數?

使用 move 關鍵字可以用來捕獲變數,並且將它們移動到閉包中,例如:

fn main() {
    let num = 5;
    let plus_num = move |x: i32| -> i32 { x + num };
    let a = plus_num(1);
    println!("a is {}", a); // a is 6
}

上面的範例中,我們定義了一個變數 num,並且將它傳遞給一個閉包 plus_num,然後呼叫 plus_num

在呼叫 plus_num 的時候,與上面其他例子不同的是,我們使用 move 關鍵字來捕獲變數,並且將它加到 x 上。

以上就是閉包的基本用法,如果有任何問題,歡迎在下方留言討論。
本文同步發表於我的技術部落格,歡迎大家有空去參觀。


上一篇
Rust 的枚舉
下一篇
Rust 的生命週期
系列文
30 天快快樂樂學 Rust 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言