欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

rust閉包的使用

 更新時間:2023年12月07日 14:47:30   作者:int8  
閉包在Rust中是非常強大的功能,允許你編寫更靈活和表達性的代碼,本文主要介紹了rust閉包的使用,具有一定的參考價值,感興趣的可以了解一下

一、閉包是什么

(一)閉包是什么

我們先來看看javascript中的閉包。
在函數(shù)外部無法讀取函數(shù)內(nèi)的局部變量。但是我們有時候需要得到函數(shù)內(nèi)的局部變量,那么如何從外部讀取局部變量?那就是在函數(shù)的內(nèi)部,再定義一個函數(shù)。

function f1(){
	var n=999;
	function f2(){
		alert(n);
	}
}

在上面的代碼中,函數(shù)f2在函數(shù)f1內(nèi)部,這時f1內(nèi)部的所有局部變量,對f2都是可見的。但是反過來就不行,f2內(nèi)部的局部變量,對f1就是不可見的。這就是"鏈式作用域",子作用域會一級一級地向上尋找所有父作用域的變量。
既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,我們不就可以在f1外部讀取它的內(nèi)部變量了嗎!

function f1(){
	var n=999;
	function f2(){
		alert(n);
	}
	return f2;
}
var result=f1();//實際上f1()執(zhí)行完之后,并沒有釋放內(nèi)存,n還在
result(); // 999。執(zhí)行f2(),能訪問f1中的n

上一節(jié)代碼中的f2函數(shù),就是閉包。
各種專業(yè)文獻上的"閉包"定義非常抽象,很難看懂。我的理解是,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
由于只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,因此可以把閉包簡單理解成"定義在一個函數(shù)內(nèi)部的函數(shù)"。
所以,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。

閉包可以讀取函數(shù)內(nèi)部的變量,可以讓這些變量的值始終保持在內(nèi)存中。
f1是f2的父函數(shù),而f2被賦給了一個全局變量,這導致f2始終在內(nèi)存中,而f2的存在依賴于f1,因此f1也始終在內(nèi)存中,不會在調(diào)用結束后,被垃圾回收機制回收。

(二)閉包的優(yōu)缺點

優(yōu)點:
直接訪問父作用域中的局部變量,避免了傳參的問題
邏輯連續(xù),避免脫離當前邏輯,在外部編寫代碼
缺點:
因為使用閉包,可以使函數(shù)在執(zhí)行完后不被銷毀,保留在內(nèi)存中,如果大量使用閉包就會造成內(nèi)存泄露,內(nèi)存消耗很大

(三)使用場景

(1)設置timer
(2)用后即棄的一次性功能,沒必要另外寫個函數(shù)

(四)思考題

如果你能理解下面兩段代碼的運行結果,應該就算理解閉包的運行機制了。
代碼片段一。

var name = "The Window";
var object = {
	name : "My Object",
	getNameFunc : function(){
		return function(){
			return this.name;
		};
	}
};
alert(object.getNameFunc()());

代碼片段二。

var name = "The Window";
var object = {
	name : "My Object",
	getNameFunc : function(){
		var that = this;
		return function(){
			return that.name;
		};
	}
};
alert(object.getNameFunc()());

第一個 打印結果為The window
第二個 打印結果為My Object
this是由它所在函數(shù)調(diào)用時的環(huán)境決定的,而不是由它所在函數(shù)定義的環(huán)境決定的。
第一個this是在調(diào)用閉包時確定的,環(huán)境是全局環(huán)境
第二個this是在調(diào)用getNameFunc時確定的,環(huán)境是object內(nèi)

二、rust閉包

rust閉包,跟javascript閉包原理基本一樣。就語法格式不一樣。
rust閉包沒有名字,包含于一個函數(shù)內(nèi)。
所以可以直接認為rust閉包是一個沒有函數(shù)名的內(nèi)聯(lián)函數(shù)。

(一)定義閉包

它的定義語法如下

|parameter| {
     // 閉包的具體邏輯
}

閉包不要求在參數(shù)和返回值上注明類型
例子

|x: u32| -> u32 { x + 1 }
|x|             { x + 1 }
|x|               x + 1  

閉包雖然沒有名稱,但我們可以將閉包賦值給一個變量

let closure_function = |parameter| {
     // 閉包的具體邏輯
}

(二)使用閉包

1.使用小括號 () 來調(diào)用閉包

closure_function(parameter);

范例:

fn main(){
     let is_even = |x| {
         x%2==0
     };
     let no = 13;
     println!("{} is even ? {}",no, is_even(no));
}
編譯運行結果如下
13 is even ? false

2.直接訪問父作用域中的變量
也叫捕獲變量。閉包周圍的作用域稱為環(huán)境
不必通過傳參的方式,而是直接訪問環(huán)境中的變量
范例:

fn main(){
     let val = 10;
     // 訪問外層作用域變量val
     let closure2 = |x| {
         x + val // 內(nèi)聯(lián)函數(shù)訪問外層作用域變量
     };
     println!("{}", closure2(2));
}
編譯運行結果如下
12

所有的閉包都實現(xiàn)了Fn、FnMut、FnOnce特性中的一個。

閉包有三種捕獲方式,Rust會根據(jù)捕獲方式來決定它們實現(xiàn)的trait。

(1)獲取所有權

使用這種方式的閉包實現(xiàn)了FnOnce特性。
閉包獲取其所有權并在定義閉包時將其移動進閉包。Once代表了閉包不能多次獲取相同變量的所有權,所以它只能被調(diào)用一次。

使用這種方式,要在開頭添加move關鍵字。這種方式用于允許閉包比其捕獲的變量活得更久,例如返回閉包或生成新線程。
例子

fn main() {
     let x = vec![1, 2, 3];
     let equal_to_x = move |z| z == x;
     println!("can't use x here: {:?}", x);
     let y = vec![1, 2, 3];
     assert!(equal_to_x(y));
}

x被移動進了閉包,因為閉包使用move關鍵字定義。接著閉包獲取了x的所有權,同時main就不再允許在println! 語句中使用x了。去掉println! 即可修復問題。

(2)可變借用
使用這種方式的閉包實現(xiàn)了FnMut特性。
因為是可變引用,所以可以改變其環(huán)境。

(3)不可變借用
使用這種方式的閉包實現(xiàn)了Fn特性。
因為是不可變引用,所以不可修改其環(huán)境。

例子

fn main() {
     let x = 5;
     let y = 10;
     // Fn閉包:通過不可變引用捕獲變量
     let add = |a| a + x;
     // FnMut閉包:通過可變引用捕獲變量
     let mut multiply = |a| {
         x * y * a
     };
     // FnOnce閉包:通過值捕獲變量
     let divide = move |a| {
         a / y
     };
     let result1 = add(3);
     let result2 = multiply(2);
     let result3 = divide(10);
     println!("The results are: {}, {}, {}", result1, result2, result3);
}

復合類型(如結構體)始終是全部捕獲的,而不是各個字段分開捕獲的。如果真要捕獲單個字段,那可能需要先借用該字段到本地局部變量中:

struct SetVec {
     set: HashSet<u32>,
     vec: Vec<u32>
}
impl SetVec {
     fn populate(&mut self) {
         let vec = &mut self.vec;
         self.set.iter().for_each(|&n| {
             vec.push(n);
         })
     }
}

相反,如果閉包直接使用了self.vec,那么它將嘗試通過可變引用捕獲self。但是因為self.set已經(jīng)被借出用來迭代了,所以代碼將無法編譯。

3.閉包作為參數(shù)和返回值
閉包可以作為函數(shù)的參數(shù)和返回值,如此使用時,必須指定類型,類型就是上面講的Fn、FnMut、FnOnce。
(1)作為參數(shù)

fn f1(x: impl Fn()){
    x();
}
fn f2<F>(x:F)
where
F:Fn()
{
     x();
}
fn main() {
     f1(||{});
     f2(||{});
}

(2)作為返回值

fn f1() -> impl Fn(i32) {
     |x|{println!("{}",x)}
}
fn f2() -> impl Fn(i32) {
     let a=100;
     move |x|{println!("{}",x+a)} //如果使用引用方式捕獲,那么返回后a銷毀,引用會變成懸垂引用,所以編譯器不會通過
}
fn main() {
     f1()(9);//9
     f2()(9);//109
}

到此這篇關于rust閉包的應用場景的文章就介紹到這了,更多相關rust閉包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • 使用systemd部署r-nacos的操作方法

    使用systemd部署r-nacos的操作方法

    r-nacos是一個用rust實現(xiàn)的nacos服務,我們用它平替java?nacos以降低服務占用內(nèi)存,提升服務的穩(wěn)定性,這篇文章主要介紹了使用systemd部署r-nacos,需要的朋友可以參考下
    2024-03-03
  • Rust之智能指針的用法

    Rust之智能指針的用法

    在Rust中,智能指針是管理內(nèi)存所有權和生命周期的核心工具,本文主要介紹了Rust之智能指針的用法,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • rust文件讀寫的實現(xiàn)示例

    rust文件讀寫的實現(xiàn)示例

    Rust語言提供了強大的文件讀寫庫,使得開發(fā)者可以更加方便地進行文件操作,并且其安全性可以有效避免文件操作中可能出現(xiàn)的風險,本文就來詳細的介紹了rust文件讀寫的實現(xiàn)示例,感興趣的可以了解一下
    2023-12-12
  • 利用rust編一個靜態(tài)博客工具

    利用rust編一個靜態(tài)博客工具

    這篇文章主要為大家詳細介紹了如何利用rust編一個靜態(tài)博客工具,這個靜態(tài)博客的工具主要是把md文檔轉(zhuǎn)為html靜態(tài)網(wǎng)站/博客,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-12-12
  • Rust之模式與模式匹配的實現(xiàn)

    Rust之模式與模式匹配的實現(xiàn)

    Rust中的模式匹配功能強大且靈活,它極大地提高了代碼的表達力和可讀性,本文主要介紹了Rust之模式與模式匹配,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • Rust 入門之函數(shù)和注釋實例詳解

    Rust 入門之函數(shù)和注釋實例詳解

    這篇文章主要為大家介紹了Rust 入門之函數(shù)和注釋實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Tauri?打開本地文件踩坑分析解決

    Tauri?打開本地文件踩坑分析解決

    這篇文章主要為大家介紹了Tauri?打開本地文件踩坑分析解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 解讀Rust的Rc<T>:實現(xiàn)多所有權的智能指針方式

    解讀Rust的Rc<T>:實現(xiàn)多所有權的智能指針方式

    Rc<T> 是 Rust 中用于多所有權的引用計數(shù)類型,通過增加引用計數(shù)來管理共享數(shù)據(jù),只有當最后一個引用離開作用域時,數(shù)據(jù)才會被釋放,Rc<T> 適用于單線程環(huán)境,并且只允許不可變共享數(shù)據(jù);需要可變共享時應考慮使用 RefCell<T> 或其他解決方案
    2025-02-02
  • Rust處理命令行參數(shù)

    Rust處理命令行參數(shù)

    在Rust中,命令行參數(shù)是程序從命令行接收的輸入,它們?yōu)槌绦蛱峁┝诉\行時配置和數(shù)據(jù)的靈活性,本文就來介紹一下Rust處理命令行參數(shù),具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 利用Rust實現(xiàn)一個簡單的Ping應用

    利用Rust實現(xiàn)一個簡單的Ping應用

    這兩年Rust火的一塌糊涂,甚至都燒到了前端,再不學習怕是要落伍了。最近翻了翻文檔,寫了個簡單的Ping應用練練手,感興趣的小伙伴可以了解一下
    2022-12-12

最新評論