函數指針
我們之前學習過向函數傳遞閉包;也可以向函數傳遞正常函數。這在我們希望傳遞已經定義的函數而不是重新定義閉包作為參數時很有用。通過函數指針允許我們使用函數作為另一個函數的參數。函數的類型是 fn (使用小寫的"f") 以免與 Fn 閉包trait相混淆。fn 被稱為 函數指針(function pointer)。指定參數為函數指針的文法類似于閉包,如示例1所示:
示例1:使用fn類型接受函數指針作為參數
這會列印出 The anser is 12。do_twice中的 f 被指定為一個接受一個i32參數并傳回i32的fn。接着就可以在do_twice函數體中調用f。在main中,可以将函數名add_one作為第一個參數傳遞給do_twice。
不同于閉包,fn是一個類型而不是一個trait,是以直接指定fn作為參數而不是聲明一個帶有Fn作為trait bound的泛型參數。
函數指針實作了所有三個閉包的trait (Fn、FnMut和FnOnce),是以總是可以在調用期望閉包的函數時傳遞函數指針作為參數。傾向于編寫使用泛型和閉包trait的函數,這樣它就能接受函數或閉包作為參數。
作為一個既可以使用内聯定義的閉包又可以使用命名函數的例子,讓我們看看一個map的應用。使用map函數将一個數字vector轉換為一個字元串vector,就可以使用閉包,比如這樣:
或者可以将函數作為map的參數來代替閉包,像這樣:
傳回閉包
閉包表現為trait,這意味首不能直接傳回閉包。對于大部分需要傳回trait的情況,可以使用實作了期望傳回trait的具體類型來替代函數的傳回值。但是這不能用于閉包,因為他們沒有一個可傳回的具體類型;例如不允許使用函數指針fn作為傳回值類型。
以下代碼嘗試直接傳回閉包,它并不能編譯:
編譯器給出的錯誤是:
錯誤又一次指向了Sized trait! Rust并不知道需要多少空間來儲存閉包。不過我們在之前了解到這種情況的解決方法:可以使用trait對象:
這段代碼就可以通過編譯。
深入學習