प्रौद्योगिकी साझेदारी

जंग प्रोग्रामिंग भाषाशिक्षणम् - कार्यात्मकभाषाविशेषताः : पुनरावर्तकाः तथा समापनम्

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

जंग क्लोजर इति अनामिकं कार्यं यत् चरे रक्षितुं शक्यते अथवा अन्येभ्यः फंक्शन्-मध्ये आर्गुमेण्ट्-रूपेण पारयितुं शक्यते । एकस्मिन् स्थाने समापनम् रचयित्वा ततः भिन्नसन्दर्भे समापनक्रियाः कर्तुं शक्नुवन्ति । कार्याणां विपरीतम्, समापनम् यस्मिन् व्याप्तेः अन्तः मूल्यानि ग्रहणं कर्तुं शक्नुवन्ति यस्मिन् व्याप्ते ते परिभाषिताः सन्ति ।

क्रमे प्रत्येकं द्रव्यं भ्रमित्वा क्रमस्य समाप्तिः कदा भवति इति निर्धारणस्य तर्कस्य उत्तरदायी पुनरावर्तकः भवति । पुनरावर्तकानां उपयोगं कुर्वन् अस्माकं एतत् तर्कं पुनः कार्यान्वितुं आवश्यकता नास्ति ।

1. समापनम्

Closure, फंक्शन्-सदृशं संरचना यत् चरे संग्रहीतुं शक्यते ।

१.१ बन्दाः स्वपर्यावरणं गृह्णन्ति

Rust इत्यस्मिन् closures इति अनामिकाः कार्याणि सन्ति ये बाह्यवातावरणात् चराः गृह्णन्ति । समापनस्य ग्रहणव्यवहारः चरप्रकारेषु, निमीलनेन तान् चरानाम् उपयोगः कथं भवति इति च निर्भरं भवति ।

मूल्येन ग्रहणं (By Value) .

यदा क्लोजरः मूल्येन चरं गृह्णाति तदा चरस्य स्वामित्वं गृह्णाति । अस्य अर्थः अस्ति यत् निमीलनस्य निर्माणानन्तरं मूलचरस्य उपयोगः न भवति ।

fn main() {
    let text = "Hello".to_string();
    // 使用 move 来显式地表示闭包将获取 text 的所有权
    let closure = move || println!("{}", text);
    // 这里 text 不能被使用,因为其所有权已经被闭包获取
    // println!("{}", text); // 这将导致编译错误
    closure(); // 打印 "Hello"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

सन्दर्भेण ग्रहणं (By Reference) २.

यदा क्लोजरः सन्दर्भेण चरं गृह्णाति तदा तत् चरं ऋणं गृह्णाति । अस्य अर्थः अस्ति यत् मूलचरः अद्यापि उपलब्धः अस्ति, परन्तु निरोधः केवलं तत् ऋणं दातुं शक्नोति, न तु स्वामित्वं ग्रहीतुं ।

fn main() {
    let text = "Hello";
    // 闭包通过引用捕获 text
    let closure = || println!("{}", text);
    // text 仍然可用,因为它没有被移动
    println!("{}", text); // 打印 "Hello"
    closure(); // 再次打印 "Hello"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

परिवर्तनीय कैप्चर

एकः समापनः परिवर्तनीयसन्दर्भं गृहीतुं शक्नोति, यत् मूलचरस्य मूल्यं परिवर्तयितुं शक्नोति ।

fn main() {
    let mut count = 0;
    // 闭包通过可变引用捕获 count
    let mut closure = || {
        count += 1; // 修改 count 的值
        println!("Count: {}", count);
    };
    closure(); // 打印 "Count: 1"
    closure(); // 打印 "Count: 2"
    // count 的值现在是 2
    println!("Final count: {}", count);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

यदि निरोधः निष्कासितः भवति mut परिवर्तनं, संकलनं विफलं भवति।

fn main() {
    let mut count = 0;
    // 闭包通过可变引用捕获 count
    let closure = || {
        count += 1; // 修改 count 的值
        println!("Count: {}", count);
    };
    closure(); // 打印 "Count: 1"
    closure(); // 打印 "Count: 2"
    // count 的值现在是 2
    println!("Final count: {}", count);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

त्रुटिसन्देशप्रोम्प्ट्: चरस्य ऋणग्रहणस्य कारणात् count,स्थानांतरण closure परिवर्तनीयबन्धनम् आवश्यकम् अस्ति ।

   Compiling playground v0.0.1 (/playground)
error[E0596]: cannot borrow `closure` as mutable, as it is not declared as mutable
 --> src/main.rs:4:9
  |
4 |     let closure = || {
  |         ^^^^^^^ not mutable
5 |         count += 1; // 修改 count 的值
  |         ----- calling `closure` requires mutable binding due to mutable borrow of `count`
...
8 |     closure(); // 打印 "Count: 1"
  |     ------- cannot borrow as mutable
9 |     closure(); // 打印 "Count: 2"
  |     ------- cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
4 |     let mut closure = || {
  |         +++

For more information about this error, try `rustc --explain E0596`.
error: could not compile `playground` (bin "playground") due to 1 previous error
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

तर्करूपेण निमीलनम्

समापनम् इव उपयोक्तुं शक्यतेपैरामीटर् पासिंगअन्येभ्यः कार्येभ्यः, वातावरणे चराः गृह्यताम् ।

fn main() {
    // 创建一个整数变量
    let number = 10;

    // 创建一个闭包,它接受一个 i32 类型的参数并返回其平方
    // 这里使用 || 表示这是一个闭包
    let square = || number * number;

    // 定义一个函数,它接受一个闭包作为参数并调用它
    // 闭包作为参数需要指定其类型,这里使用 || -> i32 表示闭包没有参数并返回 i32 类型的值
    fn call_closure<F>(f: F)
    where
        F: Fn() -> i32, // 使用 trait bound 指定闭包的签名
    {
        // 调用闭包并打印结果
        let result = f();
        println!("The result is: {}", result);
    }

    // 调用 `call_closure` 函数,并将闭包 `square` 作为参数传递
    // 由于闭包 `square` 没有参数,我们可以直接传递
    call_closure(square);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

अस्मिन् उदाहरणे - १.

  1. वयं निमीलनं परिभाषयामः square, यत् सन्दर्भेण गृह्णाति main कार्येnumber चरः तस्य वर्गं च गणयन्तु ।
  2. वयं नामकं सञ्चिकां परिभाषयामः call_closure कार्य, यद् अङ्गीकुर्वति कFn() -> i32 Trait bound closures parameters गृह्णन्ति, यस्य अर्थः अस्ति यत् closure कोऽपि parameters न गृह्णाति तथा च a प्रेषयतिi32 मूल्यस्य प्रकारः ।
  3. वयं आह्वयेम call_closure कार्यं इच्छा चsquare समापनानि तर्करूपेण पारितानि भवन्ति।यतःsquare समापनस्य मापदण्डाः नास्ति, प्रत्यक्षतया पैरामीटर् रूपेण पारयितुं शक्यतेcall_closure
  4. call_closure फंक्शन् क्लोज्र् आह्वयति, परिणामं च मुद्रयति ।

१.२ समापनप्रकारस्य अनुमानं टिप्पणी च

कार्याणां निमीलनस्य च मध्ये बहवः अधिकाः भेदाः सन्ति ।समापनार्थं सर्वदा एतादृशस्य किमपि आवश्यकता न भवतिfn पैरामीटर्स् इत्यस्य प्रकारान् निर्दिशन्तु तथा च फंक्शन्स् इव मूल्यानि रिटर्न् कुर्वन्तु । कार्येषु प्रकारटिप्पण्याः आवश्यकाः यतः ते उपयोक्त्रे उजागरितस्य स्पष्टस्य अन्तरफलकस्य भागाः सन्ति । एतानि अन्तरफलकानि कठोररूपेण परिभाषितुं महत्त्वपूर्णं यत् सर्वेषां कृते प्रयुक्तानां कार्याणां, रिटर्न्-मूल्यानां प्रकाराणां च सुसंगत-अवगमनं भवति तस्य विपरीतम्, एतादृशानां उजागरित-अन्तरफलकानां कृते समापनस्य उपयोगः न भवति: ते चर-मध्ये संगृहीताः भवन्ति, तेषां नामकरणं विना वा पुस्तकालयस्य उपयोक्तृभ्यः उजागरं विना वा उपयुज्यन्ते

समापनानि प्रायः लघु भवन्ति, तेषां सम्बन्धः कस्यापि मनमाना परिस्थितेः अपेक्षया संकीर्णसन्दर्भेण भवति । एतेषु प्रतिबन्धितसन्दर्भेषु संकलकः विश्वसनीयतया पैरामीटर्-प्रकारानाम् अनुमानं कर्तुं शक्नोति, रिटर्न्-मूल्यानां च अनुमानं कर्तुं शक्नोति, यथा अधिकांशचरानाम् प्रकारान् अनुमानयितुं शक्नोति (यद्यपि दुर्लभाः प्रकरणाः सन्ति यत्र संकलकस्य समापनप्रकारस्य टिप्पणीनां आवश्यकता भवति)

चरस्य सदृशं, यदि वयं स्पष्टतां स्पष्टतां च वर्धयितुम् इच्छामः तर्हि प्रकार-टिप्पणीः योजयितुं शक्यन्ते, यस्य दुष्परिणामः अस्ति यत् कोडं अधिकं वाचिकं भवति (सख्ततया आवश्यकस्य विरुद्धम्)

fn main() {
    let a = 100;
    let add_one = |x: i32| -> i32 { x + 1 };
    let b = add_one(a);
    println!("{}", b); 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

प्रकारटिप्पणीभिः सह समापनस्य वाक्यविन्यासः कार्याणां सदृशः अधिकः भवति । अत्र तस्य आर्गुमेण्ट् मध्ये एकं योजयति इति फंक्शन् इत्यस्य परिभाषायाः, समानव्यवहारस्य क्लोजर सिण्टैक्सस्य च लम्बवत् तुलना अस्ति । तत्र तत्सम्बद्धानां भागानां संरेखणार्थं केचन रिक्तस्थानानि योजिताः सन्ति । एतेन ज्ञायते यत् वाक्यविन्यासस्य कार्यानुष्ठानस्य कृते समापनवाक्यविन्यासः कथं समानः अस्ति, पाइप्स् इत्यस्य उपयोगं त्यक्त्वा किञ्चित् वैकल्पिकवाक्यविन्यासः च:

fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;
  • 1
  • 2
  • 3
  • 4

अतः उपर्युक्तं उदाहरणं सरलं कर्तुं शक्यते यत् :

fn main() {
    let a = 100;
    let add_one = |x| x + 1;
    let b = add_one(a);
    println!("{}", b); 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

संकलकः प्रत्येकस्य पैरामीटर् कृते ठोसप्रकारस्य अनुमानं करोति तथा च समापनपरिभाषायां मूल्यं प्रत्यागच्छति ।

अन्यत् उदाहरणं पश्यामः ।

fn main() {
    let a = 100i32;
    let a1 = 100f32;
    let closure = |x| x;
    let b = closure(a);
    let b1 = closure(a1);
    println!("{}", b); 
    println!("{}", b1); 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

ध्यानं कुर्वन्तु यत् एषा closure परिभाषा किमपि प्रकारस्य एनोटेशनं न योजयति, अतः वयं किमपि प्रकारेण सह एतत् closure आह्वयितुं शक्नुमः । परन्तु यदि भवान् द्विवारं समापनम् आह्वयितुं प्रयतते, प्रथमवारं i32 इत्यस्य उपयोगेन, द्वितीयवारं च f32 इत्यस्य उपयोगेन, तर्हि त्रुटिः निवेदिता भविष्यति:अपेक्षितम्, यतः पूर्वं "i32" प्रकारस्य तर्केन सह समापनम् आहूतम् आसीत् ।

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:6:22
  |
6 |     let b1 = closure(a1);
  |              ------- ^^ expected `i32`, found `f32`
  |              |
  |              arguments to this function are incorrect
  |
note: expected because the closure was earlier called with an argument of type `i32`
 --> src/main.rs:5:21
  |
5 |     let b = closure(a);
  |             ------- ^ expected because this argument is of type `i32`
  |             |
  |             in this closure call
note: closure parameter defined here
 --> src/main.rs:4:20
  |
4 |     let closure = |x| x;
  |                    ^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 1 previous error
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

1.3 गृहीतमूल्यानि समापनात् Fn लक्षणात् च बहिः स्थापयन्तु

एकदा निमीलनं यस्मिन् वातावरणे परिभाषितं तस्य मूल्यस्य सन्दर्भं, तस्य स्वामित्वं वा गृह्णाति (एवं किं, यदि किमपि, निमीलने स्थानान्तरितम् इति प्रभावितं करोति), समापनशरीरस्य अन्तः कोडः पश्चात् बन्दीकरणसमये सन्दर्भं परिभाषयति मूल्याङ्कितः भवति।अथवा मूल्यं कथं परिवर्तितं भवति (यत् किं प्रभावितं करोति, यदि किमपि, समापनात् निष्कासितम्)। समापनशरीरः निम्नलिखितयोः किमपि कर्तुं शक्नोति: गृहीतं मूल्यं समापनात् बहिः स्थानान्तरयितुं, गृहीतं मूल्यं परिवर्तयितुं, मूल्यं न चालयितुं न परिवर्तयितुं वा, अथवा प्रथमस्थाने कदापि मूल्यं वातावरणात् न गृह्णाति

यथा बन्दः वातावरणे मूल्यानि गृह्णाति, नियन्त्रयति च, तत् बन्देन कार्यान्वितं लक्षणं प्रभावितं करोति । लक्षणं कार्याणां संरचनानां च कृते तेषां उपयोगं कर्तुं शक्नुवन्ति निमीलनस्य प्रकारान् निर्दिष्टुं एकः उपायः अस्ति ।समापनशरीरः मूल्यानि कथं नियन्त्रयति इति अवलम्ब्य निमीलनं स्वयमेव वृद्धिशीलतया च एकं, द्वौ, त्रीणि वा कार्यान्वितं करोतिFn लक्षण।

  1. FnOnce एकवारं आह्वयितुं शक्यमाणानां समापनानाम् उपरि प्रवर्तते सर्वे समापनाः न्यूनातिन्यूनं एतत् लक्षणं कार्यान्वन्ति यतोहि सर्वे समापनाः आह्वयितुं शक्यन्ते ।निमीलनशरीरात् बहिः गृहीतमूल्यानि चालयति यत् निमीलनं केवलं कार्यान्वितं करोतिFnOnce लक्षणं यतः एकवारमेव आह्वयितुं शक्यते।
  2. FnMut निमीलनानां कृते उपयुक्तं यत् गृहीतं मूल्यं निमीलनशरीरात् बहिः न चालयति, परन्तु गृहीतमूल्यं परिवर्तयितुं शक्नोति । एतादृशं निमीलनं बहुवारं आह्वयितुं शक्यते ।
  3. Fn न च गृहीतं मूल्यं बन्दीकरणशरीरात् बहिः चालयन्ति न च गृहीतमूल्यं परिवर्तयन्ति, तथा च अवश्यमेव एतादृशानि निमीलनानि समाविष्टानि ये परिवेशात् मूल्यं न गृह्णन्ति एतादृशानि समापनानि स्वपर्यावरणस्य परिवर्तनं विना बहुवारं आह्वयितुं शक्यन्ते, यत् तेषु परिदृश्येषु महत्त्वपूर्णं भवति यत्र बन्दीकरणं बहुवारं एकत्रैव आह्वयते

अत्र फंक्शन् मध्ये कथं तस्य उपयोगः करणीयः इति दर्शयति उदाहरणम् FnOnce सामान्यबाधारूपेण तथा सुनिश्चितं कुर्वन्तु यत् समापनम् एकवारं एव आह्वयते:

fn call_once<F, T>(f: F) -> T
where
    F: FnOnce() -> T, // 约束 F 为 FnOnce trait,意味着它接受一个空参数并返回 T 类型
{
    f() // 调用闭包并返回结果
}

fn main() {
    // 创建一个闭包,它捕获了 `value` 的所有权
    let value = 42;
    let consume = move || {
        let result = value; // 移动 `value`
        println!("The value is: {}", result);
        result // 返回结果
    };

    // 调用 `call_once` 函数,传入闭包
    let result = call_once(consume);
    println!("Result of the closure: {}", result);

    // 尝试再次使用 `consume` 将会导致编译错误,因为它已经消耗了 `value`
    // call_once(consume);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

संचालन परिणाम

The value is: 42
Result of the closure: 42
  • 1
  • 2

अस्मिन् उदाहरणे वयं सामान्यं फंक्शन् परिभाषयामः call_once, यत् एकं प्रकारं स्वीकुर्वति F पैरामीटर्f,इत्यस्मिन्‌ F अवश्यं साधितव्यम्FnOnce लक्षण।इति भावःf रिक्तमापदण्डान् स्वीकृत्य प्रकारं प्रत्यागच्छति इति समापनम् अस्तिT इति परिणामः ।

अस्ति main फंक्शन् मध्ये वयं closure रचयामःconsume, यत् गृह्णाति value स्वामित्वस्य ।ततः, वयं आह्वयेमcall_once कार्यम्, पारितम्consume समापनम् ।call_once फंक्शन् क्लोज्रं आह्वयति तस्य परिणामं च ददाति ।यतःconsume समापनम् उपभोक्तम् अस्तिvalue, पुनः आह्वानं कर्तुं प्रयतस्व call_once एकस्मिन् एव निरोधे पारितस्य परिणामः संकलनदोषः भविष्यति ।

अत्र प्रयोगः FnMut लक्षणानाम् उदाहरणानि ।

fn apply_mut<F, T>(func: &mut F, num: i32) -> T
where
    F: FnMut(i32) -> T, // F 是一个可变闭包,接受一个 i32 类型的参数并返回类型为 T 的结果
{
    func(num) // 调用闭包并返回结果
}

fn main() {
    let mut count = 0;

    // 创建一个闭包,它接受一个 i32 类型的参数并将其加到 count 上
    let mut increment = |num: i32| -> i32 {
        count += num;
        count
    };

    // 使用 apply_mut 函数和 increment 闭包的引用
    let result: i32 = apply_mut(&mut increment, 5);
    println!("Result after applying increment: {}", result);

    // 再次使用 apply_mut 函数和 increment 闭包的引用
    let result: i32 = apply_mut(&mut increment, 10);
    println!("Result after applying increment again: {}", result);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

संचालन परिणाम

Result after applying increment: 5
Result after applying increment again: 15
  • 1
  • 2

अस्मिन् उदाहरणे .apply_mut कार्यं स्वीकुर्वति कF प्रकारस्य परिवर्तनीयः सन्दर्भः&mut F पैरामीटर् इव (तथा,increment निमीलनं न चालितं भविष्यति बहुवारं च उपयोक्तुं शक्यते) तथा च कi32 प्रकार मापदण्डnumwhere वाक्यं निर्दिशतिF अवश्यं कार्यान्वयनम्FnMut निमीलनम्, यत् स्वीकुर्वति कi32 type parameters and returns a type ofT इति परिणामः ।main कार्ये परिवर्तनीयं निमीलनं निर्मीयतेincrement, यत् गृहीतं चरं परिवर्तयति count, ततः प्रयोगः apply_mut एतत् समापनम् आह्वयितुं function इति ।प्रत्येकं आह्वानम्apply_mut उपयोगं करिष्यतिincrement निमीलनम्, चincrement समापनम् परिवर्तितं भविष्यतिcount मूल्यम्‌।

रस्ट् इत्यत्र २.Fn लक्षणस्य अर्थः अस्ति यत् निमीलनं गृह्णाति चरानाम् स्वामित्वं न गृह्णाति, न च तान् चरानाम् परिवर्तनं करोति ।निम्नलिखित उदाहरणं दर्शयति यत् accept इत्यस्य परिभाषा कथं भवतिFn फंक्शन् इत्यस्य आर्गुमेण्ट् इति रूपेण क्लोज् कृत्वा समवर्ती परिदृश्येषु तस्य उपयोगं कुर्वन्तु ।

use std::thread;

// 定义一个函数,它接受一个实现了 Fn(i32) -> i32 的闭包,并调用它
fn call_once<F, T>(func: F) -> T
where
    F: Fn(i32) -> T, // 指定 F 是一个接受 i32 并返回 T 的 Fn 闭包
{
    let result = func(42); // 调用闭包,传入一个 i32 类型的值
    result // 返回闭包的执行结果
}

fn main() {
    // 定义一个简单的 Fn 闭包,它接受一个 i32 类型的参数并返回两倍的该值
    let double = |x: i32| -> i32 {
        x * 2
    };

    // 创建多个线程,每个线程都使用相同的闭包
    let handles: Vec<_> = (0..5).map(|i| {
        let func = double; // 闭包可以被复制,因为它是 Fn 类型的
        thread::spawn(move || {
            let result = call_once(func); // 调用 call_once 函数,并传入闭包
            println!("Thread {} result: {}", i, result); // 打印结果
        })
    }).collect();

    // 等待所有线程完成
    for handle in handles {
        handle.join().unwrap();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

प्रत्येकं रन अस्मिन् क्रमे न भवति ।

संचालन परिणाम

Thread 1 result: 84
Thread 2 result: 84
Thread 0 result: 84
Thread 4 result: 84
Thread 3 result: 84
  • 1
  • 2
  • 3
  • 4
  • 5

अस्मिन् उदाहरणे - १.

  1. वयं क call_once function, यत् सामान्यं पैरामीटर् स्वीकुर्वतिF,तथा F अवश्यं तृप्तः भवतिFn(i32) -> T लक्षण सीमा।इति भावःF इति निमीलनं स्वीकुर्वति कi32 type parameters and returns a type ofT इति परिणामः ।
  2. अस्ति main फंक्शन् मध्ये वयं सरलं closure परिभाषयामःdouble, यत् अङ्गीकुर्वति i32 प्रकार मापदण्डx तथा प्रत्यागच्छतिx * 2 इति परिणामः ।
  3. वयं उपयुञ्ज्महे map ५ सूत्राणि निर्मीयन्ते, प्रत्येकं सूत्रं प्रतिलिपितः भवतिdouble बन्दं कृत्वा नूतनसूत्रे आह्वयन्तुcall_once function, closure इत्यस्य argument रूपेण पारयन्call_once
  4. प्रत्येकं सूत्रे, २.call_once फंक्शन् आह्वयते, क्लोजरः निष्पादितः भवति, परिणामः च मुद्रितः भवति ।
  5. अन्ते वयं उपयुञ्ज्महे join विधिः सर्वेषां सूत्राणां पूर्णतां प्रतीक्षते ।

2. पुनरावर्तकः

पुनरावर्तकाः भवन्तं क्रमस्य द्रव्येषु किञ्चित् संसाधनं कर्तुं शक्नुवन्ति । तदनन्तरं वयं मुख्यतया एलिमेण्ट् अनुक्रमं संसाधितुं पुनरावर्तकानां उपयोगं परिचययामः तथा च लूप्स् VS पुनरावर्तकानां प्रदर्शनतुलनाम् । Rust इत्यस्मिन् पुनरावर्तकाः आलस्ययुक्ताः भवन्ति, यस्य अर्थः अस्ति यत् यावत् पुनरावर्तकं उपभोक्तृविधिः न आहूयते तावत् कोऽपि क्रिया न क्रियते ।

२.१ पुनरावर्तकगुणः अग्रिमविधिः च

पुनरावर्तकाः सर्वे नामकं फंक्शन् कार्यान्वन्ति Iterator मानकपुस्तकालयस्य लक्षणे परिभाषितः अस्ति । अस्य लक्षणस्य परिभाषा एतादृशी दृश्यते-

pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
    // 此处省略了方法的默认实现
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

type Item तथाSelf::Item , ते लक्षणस्य सम्बद्धं प्रकारं परिभाषयन्ति ।परन्तु इदानीं कृते भवद्भिः केवलं ज्ञातव्यं यत् एषः कोड् कथं कार्यान्वयनीयम् इति दर्शयतिIterator लक्षणानाम् आवश्यकता अस्ति यत् कItem प्रकारः इतिItem प्रकारः यथा प्रयुक्तःnext मेथड् इत्यस्य रिटर्न् वैल्यू प्रकारः । अन्येषु शब्देषु, २.Item प्रकारः पुनरावर्तकेन ​​प्रत्यागतस्य तत्त्वस्य प्रकारः भविष्यति ।

next आम्‌Iterator एकमात्रं विधिकार्यन्वयकाः परिभाषितुं आवश्यकाः सन्ति ।next पुनरावर्तके एकैकं द्रव्यं प्रत्यागच्छति, incapsulated inSome , यदा पुनरावर्तकः समाप्तः भवति तदा पुनः आगच्छतिNone

२.२ पुनरावर्तकानां उपभोगस्य पद्धतयः

Iterator लक्षणानाम् एकः भिन्नविधिसमूहः अस्ति यः पूर्वनिर्धारितरूपेण मानकपुस्तकालयेन प्रदत्तः भवति;Iterator एतानि सर्वाणि पद्धतयः लक्षणस्य मानकपुस्तकालयस्य एपिआइ दस्तावेजीकरणे दृश्यन्ते ।केचन पद्धतयः स्वपरिभाषायां आह्वयन्तिnext विधिः, यस्मात् कारणात् कार्यान्वयनेIterator लक्षणं कार्यान्वितुं आवश्यकम् अस्तिnext विधिकारणानि ।

एते आह्वानाः next मेथड्स् इत्यस्य पद्धतयः उपभोग्य एडाप्टर् इति उच्यन्ते यतः तान् आह्वयन् पुनरावर्तकाः उपभोगं कुर्वन्ति ।

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    // 使用into_iter()将Vec转换为消费迭代器
    let numbers_iter = numbers.iter();
    let mut sum: i32 = numbers_iter
        // 使用sum适配器计算迭代器中所有元素的总和
        .sum();

    // 打印总和
    println!("The sum is: {}", sum);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

यदि पुनः तस्य उपयोगं करोति numbers_iter त्रुटिः निवेदिता भविष्यति।sum विधिः पुनरावर्तकस्य स्वामित्वं गृहीत्वा पुनः पुनः आह्वयतिnext पुनरावर्तकस्य उपरि पुनरावृत्तिं कर्तुं, एवं पुनरावर्तकस्य उपभोगं कर्तुं। यथा यथा प्रत्येकस्य द्रव्यस्य उपरि पुनरावृत्तिः भवति तथा तथा प्रत्येकं द्रव्यं योगे योजयति, पुनरावृत्तिः समाप्ते सति योगं च प्रत्यागच्छति ।स्थानांतरणsum न पुनः प्रयोगः अनुमतःnumbers_iter, यतः आह्वानम् sum यदा पुनरावर्तकस्य स्वामित्वं गृह्णाति।

२.३ अन्येषां पुनरावर्तकानां जननार्थं पद्धतयः

Iterator लक्षणेषु परिभाषितः अन्यः विधिवर्गः, यः iterator adapters इति उच्यते, अस्मान् वर्तमान iterator इत्येतत् भिन्नप्रकारस्य iterator इत्यत्र परिवर्तयितुं शक्नोति । एकस्मिन् श्रृङ्खले बहुविधाः पुनरावर्तक-एडाप्टर्-आह्वानं कर्तुं शक्यन्ते । परन्तु सर्वे पुनरावर्तकाः आलस्ययुक्ताः इति कारणतः पुनरावर्तक-एडाप्टर-आह्वानस्य परिणामं प्राप्तुं उपभोक्तृ-एडाप्टर्-विधिः आह्वनीया ।

fn main() {
    let v1: Vec<i32> = vec![1, 2, 3];
    let v2: Vec<_> = v1.iter().map(|x| x * x).collect();
    assert_eq!(v2, vec![1, 4, 9]);
}
  • 1
  • 2
  • 3
  • 4
  • 5

collect विधिः पुनरावर्तकस्य उपभोगं करोति, परिणामान् च दत्तांशसंरचनायां संग्रहयति ।यतःmap एकं समापनम् प्राप्नोति यत् भवन्तः प्रत्येकं तत्त्वे यत्किमपि कार्यं कर्तुम् इच्छन्ति तत् निर्दिष्टुं शक्नुवन्ति यत् तत् भ्रमति ।

२.४ तेषां वातावरणं गृह्णन्ति ये समापनम्

अनेकाः पुनरावर्तक-एडाप्टर्-इत्येतत् समापनम् मापदण्डरूपेण स्वीकुर्वन्ति, सामान्यतया च पुनरावर्तक-एडाप्टर-मापदण्डरूपेण निर्दिष्टं समापनं तस्य वातावरणं गृह्णाति इति समापनम् भविष्यति

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    // 使用into_iter()将Vec转换为消费迭代器
    let filtered_and_squared: Vec<i32> = numbers.into_iter()
        // 使用filter适配器过滤元素,接受一个闭包作为参数
        // 闭包捕获其环境,这里指numbers的元素
        .filter(|&x| x % 2 == 0) // 保留偶数
        // 使用map适配器对过滤后的元素进行变换,也接受一个闭包
        .map(|x| x * x) // 对每个元素进行平方
        // 使用collect适配器将结果收集到一个新的Vec中
        .collect();

    // 打印过滤和平方后的结果
    println!("The filtered and squared numbers are: {:?}", filtered_and_squared);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

संचालन परिणाम

The filtered and squared numbers are: [4, 16]
  • 1

अस्मिन् उदाहरणे .filter तथाmap उभौ अपि पुनरावर्तक-एडाप्टर् स्तः, ते समापनम् पैरामीटर्-रूपेण स्वीकुर्वन्ति । एते निरोधाः स्वपर्यावरणं अर्थात् पुनरावर्तके तत्त्वानि गृह्णन्ति ।अस्तिfilter एडाप्टरे, समापनम्|&x| x % 2 == 0 तत्त्वं समसङ्ख्या अस्ति वा इति परीक्षितुं प्रयुक्तम्, यदि अस्ति तर्हि तत्त्वं धारयिष्यते ।अस्तिmap एडाप्टरे, समापनम्|x| x * x प्रत्येकं तत्त्वस्य वर्गीकरणाय प्रयुक्तम् । एते एडाप्टर् उपभोक्तृत्वात् ते मूलपुनरावृत्तिकर्तारं उपभोगयन्ति अतः पुनः उपयोक्तुं न शक्यन्ते । अन्ते, २.collect एडाप्टरः संसाधिततत्त्वान् नूतनरूपेण संग्रहयतिVec मध्यं।

२.५ लूप् VS पुनरावर्तकस्य कार्यक्षमतायाः तुलना

पुनरावर्तकाः, उच्चस्तरीयः अमूर्ततारूपेण, हस्तलिखितस्य निम्नस्तरीयसङ्केतस्य इव मोटेन समानप्रदर्शनेन कोडरूपेण संकलिताः भवन्ति । पुनरावर्तकाः Rust इत्यस्य शून्य-लाभ-अमूर्तीकरणेषु अन्यतमम् अस्ति, यस्य अर्थः अस्ति यत् अमूर्तीकरणं कोऽपि रनटाइम् ओवरहेड् न प्रवर्तयति ।

fn main() {
    let numbers1 = (0..1000000).collect::<Vec<i64>>();
    let numbers2 = (0..1000000).collect::<Vec<i64>>();

    let mut sum1 = 0i64;
    let mut sum2 = 0i64;

    // 测量for循环的性能
    let start = std::time::Instant::now();
    for val in numbers1 {
        sum1 += val;
    }
    let loop_duration = start.elapsed();

    // 测量迭代器的性能
    let start = std::time::Instant::now();
    for val in numbers2.iter() {
        sum2 += val;
    }
    let iterator_duration = start.elapsed();

    println!("Iterator took: {:?}", iterator_duration);
    println!("For loop took: {:?}", loop_duration);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

संचालन परिणाम

Iterator took: 12.796012ms
For loop took: 11.559512ms

Iterator took: 12.817732ms
For loop took: 11.687655ms

Iterator took: 12.75484ms
For loop took: 11.89468ms

Iterator took: 12.812022ms
For loop took: 11.785106ms

Iterator took: 12.78293ms
For loop took: 11.528941ms
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

अस्मात् उदाहरणात् भवन्तः द्रष्टुं शक्नुवन्ति यत् पुनरावर्तकाः अद्यापि किञ्चित् मन्दतराः सन्ति ।

सन्दर्भलिङ्कः

  1. जंग आधिकारिकजालस्थलम् : १.https://www.rust-lang.org/zh-CN इति ग्रन्थः
  2. जंग आधिकारिक दस्तावेजीकरण : १.https://doc.rust-lang.org/ इति वृत्तान्तः ।
  3. जंग क्रीडा : २.https://play.rust-lang.org/ इति वृत्तान्तः ।
  4. "जंग प्रोग्रामिंग भाषा"