Chắc chắn bạn có thể:
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, ×2);
}
Vì đây là Rust, bạn phải tính đến quyền sở hữu và thời gian tồn tại của việc đóng .
TL; DR; Về cơ bản, có 3 loại bao đóng (đối tượng có thể gọi):
Fn
: Nó không thể sửa đổi các đối tượng mà nó chụp.
FnMut
: Nó có thể sửa đổi các đối tượng mà nó chụp.
FnOnce
: Hạn chế nhất. Chỉ có thể được gọi một lần bởi vì khi nó được gọi là nó tự tiêu thụ và bắt giữ nó.
Xem Khi nào thì một bao đóng triển khai Fn, FnMut và FnOnce? để biết thêm chi tiết
Nếu bạn đang sử dụng một con trỏ đến hàm đơn giản như bao đóng, thì tập hợp chụp ảnh trống và bạn có Fn
hương vị.
Nếu bạn muốn làm những thứ lạ mắt hơn, thì bạn sẽ phải sử dụng các hàm lambda.
Trong Rust có các con trỏ thích hợp đến các hàm, hoạt động giống như các hàm trong C. Ví dụ như kiểu của chúng fn(i32) -> i32
. Các Fn(i32) -> i32
, FnMut(i32) -> i32
và FnOnce(i32) -> i32
thực sự là đặc điểm. Một con trỏ đến một hàm luôn triển khai cả ba điều này, nhưng Rust cũng có các bao đóng, có thể hoặc không được chuyển đổi thành con trỏ (tùy thuộc vào việc tập hợp chụp trống) thành các hàm nhưng chúng thực hiện một số đặc điểm này.
Vì vậy, ví dụ, ví dụ từ trên có thể được mở rộng:
fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
fun_test_dyn(5, ×2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x);
fun_test_ptr(5, |x| y*x);
}