एक कार्यक्रम एक बंद का उपयोग क्यों करेगा?


58

कई पदों को बंद करने के बारे में समझाने के बाद यहाँ मुझे अभी भी एक महत्वपूर्ण अवधारणा याद आ रही है: एक क्लोजर क्यों लिखें? एक प्रोग्रामर क्या विशिष्ट कार्य करेगा जो एक बंद द्वारा सबसे अच्छा काम किया जा सकता है?

स्विफ्ट में बंद होने के उदाहरण एक NSUrl की पहुंच है और रिवर्स जियोकोडर का उपयोग कर रहे हैं। ऐसा ही एक उदाहरण है। दुर्भाग्य से, वे पाठ्यक्रम सिर्फ बंद करने के लिए प्रस्तुत करते हैं; वे यह नहीं समझाते हैं कि कोड समाधान को बंद करने के रूप में क्यों लिखा गया है।

एक वास्तविक विश्व प्रोग्रामिंग समस्या का एक उदाहरण जो कहने के लिए मेरे मस्तिष्क को ट्रिगर कर सकता है, "अहा, मुझे इसके लिए एक बंद लिखना चाहिए", एक सैद्धांतिक चर्चा की तुलना में अधिक जानकारीपूर्ण होगा। इस साइट पर उपलब्ध सैद्धांतिक चर्चाओं की कोई कमी नहीं है।


7
"हाल ही में यहाँ क्लोज़र की समीक्षा की गई है" - क्या आप एक लिंक याद कर रहे हैं?
दान पीचेलमैन ने

2
आपको प्रासंगिक उत्तर के नीचे एक टिप्पणी में अतुल्यकालिक कार्य के बारे में स्पष्टीकरण देना चाहिए । यह आपके मूल प्रश्न का हिस्सा नहीं है, और उत्तर देने वाले को आपके संपादन की सूचना कभी नहीं मिलेगी।
रॉबर्ट हार्वे

5
बस एक टिडबिट: क्लोजर का महत्वपूर्ण बिंदु लेक्सिकल स्कूपिंग है (डायनेमिक स्कूपिंग के विपरीत), लेक्सिकल स्कूपिंग के बिना क्लोज़र थोड़े बेकार हैं। क्लोजर को कभी-कभी लेक्सिकल क्लोजर भी कहा जाता है।
हॉफमैन

1
क्लोजर आपको कार्यों को तत्काल करने की अनुमति देते हैं ।
user253751

1
कार्यात्मक प्रोग्रामिंग पर कोई अच्छी पुस्तक पढ़ें। शायद SICP के
बेसिल स्ट्रायनेवविच

जवाबों:


33

सबसे पहले, ऐसा कुछ भी नहीं है जो क्लोजर का उपयोग किए बिना असंभव है। आप हमेशा किसी विशिष्ट इंटरफ़ेस को लागू करने वाले ऑब्जेक्ट द्वारा एक क्लोजर को बदल सकते हैं। यह केवल संक्षिप्तता और कम युग्मन की बात है।

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

जहां अन्य निर्माणों पर क्लोजर वास्तव में चमकते हैं, उच्च-क्रम वाले फ़ंक्शंस का उपयोग करते समय, जब आपको वास्तव में राज्य को संवाद करने की आवश्यकता होती है, और आप इसे एक-लाइनर बना सकते हैं, जैसा कि इस जावास्क्रिप्ट उदाहरण में क्लोज़र पर विकिपीडिया पृष्ठ से है :

// Return a list of all books with at least 'threshold' copies sold.
function bestSellingBooks(threshold) {
  return bookList.filter(
      function (book) { return book.sales >= threshold; }
    );
}

यहाँ, thresholdबहुत रसीला और स्वाभाविक रूप से संचार किया गया है जहां से यह परिभाषित किया जाता है कि इसका उपयोग कहां किया जाता है। इसका दायरा जितना संभव हो उतना छोटा सीमित है। filterएक थ्रेशोल्ड की तरह क्लाइंट-परिभाषित डेटा को पारित करने की संभावना के लिए लिखने के लिए लिखना नहीं पड़ता है। हमें इस एक छोटे से समारोह में दहलीज को संप्रेषित करने के एकमात्र उद्देश्य के लिए किसी भी मध्यवर्ती संरचनाओं को परिभाषित करने की आवश्यकता नहीं है। यह पूरी तरह से आत्म-निहित है।

आप इसे बंद किए बिना लिख सकते हैं , लेकिन इसके लिए बहुत अधिक कोड की आवश्यकता होगी, और इसका पालन करना कठिन होगा। इसके अलावा, जावास्क्रिप्ट में एक काफी वर्बोस लैम्बडा सिंटैक्स है। उदाहरण के लिए स्काला में, संपूर्ण कार्य निकाय होगा:

bookList filter (_.sales >= threshold)

यदि आप हालांकि ECMAScript 6 का उपयोग कर सकते हैं , तो वसा तीर फ़ंक्शन के लिए भी जावास्क्रिप्ट कोड बहुत सरल हो जाता है और वास्तव में एक ही लाइन पर रखा जा सकता है।

const bestSellingBooks = (threshold) => bookList.filter(book => book.sales >= threshold);

अपने स्वयं के कोड में, उन जगहों की तलाश करें जहां आप बहुत सारे बॉयलरप्लेट उत्पन्न करते हैं, ताकि एक स्थान से दूसरे स्थान तक अस्थायी मूल्यों को संवाद किया जा सके। ये एक बंद के साथ बदलने पर विचार करने के लिए उत्कृष्ट अवसर हैं।


वास्तव में क्लोजिंग कपलिंग को कैसे कम करते हैं?
sbichenko

क्लोजर के बिना, आपको bestSellingBooksकोड और कोड दोनों पर प्रतिबंध लगाना होगा filter, जैसे कि एक विशिष्ट इंटरफ़ेस या उपयोगकर्ता डेटा तर्क, ताकि thresholdडेटा संवाद करने में सक्षम हो सके । यह दोनों कार्यों को एक साथ बहुत कम पुन: प्रयोज्य तरीकों से जोड़ता है।
कार्ल बेज़ेलफेल्ट

51

स्पष्टीकरण के माध्यम से, मैं इस उत्कृष्ट ब्लॉग पोस्ट से कुछ कोड उधार लेने जा रहा हूं । यह जावास्क्रिप्ट है, लेकिन यह भाषा सबसे ब्लॉग पोस्ट है जो क्लोजर उपयोग के बारे में बात करती है, क्योंकि क्लोज़र जावास्क्रिप्ट में बहुत महत्वपूर्ण हैं।

मान लीजिए कि आप एक सारणी को HTML तालिका के रूप में प्रस्तुत करना चाहते हैं। आप इसे इस तरह से कर सकते हैं:

function renderArrayAsHtmlTable (array) {
  var table = "<table>";
  for (var idx in array) {
    var object = array[idx];
    table += "<tr><td>" + object + "</td></tr>";
  }
  table += "</table>";
  return table;
}

लेकिन आप जावास्क्रिप्ट की दया पर हैं कि कैसे सरणी में प्रत्येक तत्व प्रदान किया जाएगा। यदि आप रेंडरिंग को नियंत्रित करना चाहते हैं, तो आप ऐसा कर सकते हैं:

function renderArrayAsHtmlTable (array, renderer) {
  var table = "<table>";
  for (var idx in array) {
    var object = array[idx];
    table += "<tr><td>" + renderer(object) + "</td></tr>";
  }
  table += "</table>";
  return table;
}

और अब आप केवल एक फ़ंक्शन पास कर सकते हैं जो आपके द्वारा प्रदान किए जाने वाले रिटर्न को लौटाता है।

यदि आप प्रत्येक तालिका पंक्ति में कुल भाग प्रदर्शित करना चाहते हैं तो क्या होगा? आपको उस कुल ट्रैक करने के लिए एक चर की आवश्यकता होगी, है ना? एक क्लोजर आपको रेंडरर फ़ंक्शन लिखने की अनुमति देता है जो रनिंग टोटल वैरिएबल को बंद कर देता है, और आपको रेंडरर लिखने की अनुमति देता है जो रनिंग टोटल का ट्रैक रख सकता है:

function intTableWithTotals (intArray) {
  var total = 0;
  var renderInt = function (i) {
    total += i;
    return "Int: " + i + ", running total: " + total;
  };
  return renderObjectsInTable(intArray, renderInt);
}

यहां जो जादू हो रहा है, वह है कि चर renderInt तक पहुंच बनाए totalरखना, भले ही renderIntबार-बार कहा जाता है और बाहर निकलता है।

जावास्क्रिप्ट की तुलना में अधिक परंपरागत रूप से ऑब्जेक्ट-ओरिएंटेड भाषा में, आप एक वर्ग लिख सकते हैं जिसमें यह कुल चर है, और एक क्लोजर बनाने के बजाय इसे पास करें। लेकिन एक करीबी इसे करने का एक बहुत अधिक शक्तिशाली, स्वच्छ और सुरुचिपूर्ण तरीका है।

आगे की पढाई


10
सामान्य तौर पर, आप कह सकते हैं कि "प्रथम श्रेणी के कार्य == ऑब्जेक्ट केवल एक विधि के साथ", "क्लोजर == ऑब्जेक्ट केवल एक विधि और स्थिति के साथ", "ऑब्जेक्ट == क्लोजर का बंडल"।
जोर्ग डब्ल्यू मित्तग

अछा लगता है। एक और बात है, और यह पांडित्य हो सकता है, कि जावास्क्रिप्ट है है वस्तु उन्मुख, और आप कर सकता है एक वस्तु है कि कुल परिवर्तनीय शामिल बना सकते हैं और है कि चारों ओर गुजरती हैं। क्लोज़र बहुत अधिक शक्तिशाली, स्वच्छ और सुरुचिपूर्ण बने हुए हैं, और कहीं अधिक मुहावरेदार जावास्क्रिप्ट के लिए भी बनाते हैं, लेकिन जिस तरह से लिखा गया है, उसका अर्थ यह हो सकता है कि जावास्क्रिप्ट ऑब्जेक्ट-ओरिएंटेड तरीके से ऐसा नहीं कर सकता है।
केरेन

2
वास्तव में, वास्तव में पांडित्य होना : क्लोज़र वही हैं जो जावास्क्रिप्ट ऑब्जेक्ट को पहली जगह में उन्मुख बनाता है! OO डेटा एब्स्ट्रैक्शन के बारे में है, और क्लोज़र जावास्क्रिप्ट में डेटा एब्सट्रैक्शन करने का तरीका है।
जोर्ग डब्ल्यू मित्तग

@ JörgWMittag: जैसे आप केवल एक विधि के साथ ऑब्जेक्ट के रूप में क्लॉर्स देख सकते हैं, आप ऑब्जेक्ट को क्लोजर के संग्रह के रूप में देख सकते हैं जो समान चर पर बंद होते हैं: ऑब्जेक्ट के सदस्य चर ऑब्जेक्ट के निर्माता के स्थानीय चर और ऑब्जेक्ट के तरीके हैं कंस्ट्रक्टर के दायरे के अंदर क्लोजर को परिभाषित किया गया है और बाद में कहलाने के लिए उपलब्ध कराया गया है। कंस्ट्रक्टर फ़ंक्शन एक उच्च-क्रम फ़ंक्शन (ऑब्जेक्ट) को लौटाता है जो कि प्रत्येक बंद पर भेजे जाने वाले विधि के नाम के अनुसार प्रेषण के लिए उपयोग किया जाता है।
जियोर्जियो

@Giorgio: वास्तव में, यह है कि वस्तुओं को आम तौर पर योजना में कैसे लागू किया जाता है, उदाहरण के लिए, और यह वास्तव में यह भी है कि कैसे जावास्क्रिप्ट में वस्तुओं को लागू किया जाता है (योजना के अपने करीबी रिश्ते को देखते हुए आश्चर्य की बात नहीं है, आखिरकार, ब्रेंडन ईच को मूल रूप से डिजाइन करने के लिए काम पर रखा गया था) स्कीम को नेटस्केप नेविगेटर के अंदर एक अंतःस्थापित योजना दुभाषिया को लागू करने और लागू करने के लिए, और बाद में केवल उन वस्तुओं के साथ एक भाषा बनाने का आदेश दिया गया था जो सी ++ की तरह दिखती हैं (जिसके बाद उन्होंने उन विपणन आवश्यकताओं का पालन करने के लिए परिवर्तनों की पूर्ण न्यूनतम राशि बनाई)।
जोर्ग डब्ल्यू मित्तग

22

का उद्देश्य closuresकेवल राज्य को संरक्षित करना है; इसलिए नाम closure- यह राज्य के ऊपर बंद हो जाता है। आगे की व्याख्या में आसानी के लिए, मैं जावास्क्रिप्ट का उपयोग करूँगा।

आमतौर पर आपके पास एक फ़ंक्शन होता है

function sayHello(){
    var txt="Hello";
    return txt;
}

जहां चर का दायरा इस फ़ंक्शन के लिए बाध्य है। इसलिए निष्पादन के बाद चर txtदायरे से बाहर हो जाता है। फ़ंक्शन के निष्पादन के बाद इसे एक्सेस करने या इसका उपयोग करने का कोई तरीका नहीं है।

क्लोज़र भाषा निर्माण हैं, जो अनुमति देते हैं - जैसा कि पहले कहा गया था - चर की स्थिति को संरक्षित करने और इसलिए गुंजाइश को लम्बा खींचने के लिए।

यह विभिन्न मामलों में उपयोगी हो सकता है। एक उपयोग मामला उच्च आदेश कार्यों का निर्माण है ।

गणित और कंप्यूटर विज्ञान में, एक उच्च-क्रम फ़ंक्शन (कार्यात्मक रूप, कार्यात्मक या फ़ंक्टर) भी एक फ़ंक्शन है जो निम्न में से कम से कम एक करता है: 1

  • इनपुट के रूप में एक या अधिक कार्य करता है
  • एक फ़ंक्शन को आउटपुट करता है

एक सरल, लेकिन सराहनीय रूप से सभी उपयोगी उदाहरण नहीं है:

 makeadder=function(a){
     return function(b){
         return a+b;
     }
 }

 add5=makeadder(5);
 console.log(add5(10)); 

आप एक फ़ंक्शन को परिभाषित करते हैं makedadder, जो इनपुट के रूप में एक पैरामीटर लेता है और एक फ़ंक्शन देता है । एक बाहरी फ़ंक्शन function(a){}और एक आंतरिक है function(b){}{} । आपके द्वारा add5उच्चतर क्रमिक म्यूटेशन को कॉल करने के परिणामस्वरूप एक अन्य फ़ंक्शन को परिभाषित किया जाता है makeaddermakeadder(5)एक अनाम ( आंतरिक ) फ़ंक्शन देता है, जो बदले में 1 पैरामीटर लेता है और बाहरी फ़ंक्शन के पैरामीटर और आंतरिक फ़ंक्शन के पैरामीटर का योग देता है ।

चाल है कि लौटने जबकि, है आंतरिक समारोह है, जो वास्तविक जोड़ने करता है, बाहरी समारोह के पैरामीटर के दायरे ( a) संरक्षित है। add5 याद है , कि पैरामीटर aथा 5

या कम से कम किसी तरह उपयोगी उदाहरण दिखाने के लिए:

  makeTag=function(openTag, closeTag){
     return function(content){
         return openTag +content +closeTag;
     }
 }

 table=makeTag("<table>","</table>")
 tr=makeTag("<tr>", "</tr>");
 td=makeTag("<td>","</td>");
 console.log(table(tr(td("I am a Row"))));

एक अन्य सामान्य यूएससेक तथाकथित आईआईएफई = तुरंत फंक्शन एक्सप्रेशन है। यह जावास्क्रिप्ट में नकली निजी सदस्य चर के लिए बहुत आम है । यह एक फ़ंक्शन के माध्यम से किया जाता है, जो एक निजी गुंजाइश बनाता है = closure, क्योंकि यह परिभाषा लागू होने के तुरंत बाद है। संरचना है function(){}()()परिभाषा के बाद कोष्ठक पर ध्यान दें । यह मॉड्यूल पैटर्न का खुलासा करने के साथ ऑब्जेक्ट-निर्माण के लिए इसका उपयोग करना संभव बनाता है । चाल एक गुंजाइश बना रही है और एक वस्तु लौटा रही है, जिसे आईआईएफई के निष्पादन के बाद इस दायरे तक पहुंच है।

Addi का उदाहरण इस तरह दिखता है:

 var myRevealingModule = (function () {

         var privateVar = "Ben Cherry",
             publicVar = "Hey there!";

         function privateFunction() {
             console.log( "Name:" + privateVar );
         }

         function publicSetName( strName ) {
             privateVar = strName;
         }

         function publicGetName() {
             privateFunction();
         }


         // Reveal public pointers to
         // private functions and properties

         return {
             setName: publicSetName,
             greeting: publicVar,
             getName: publicGetName
         };

     })();

 myRevealingModule.setName( "Paul Kinlan" );

लौटी हुई वस्तु में फ़ंक्शंस (उदाहरण publicSetName) के संदर्भ होते हैं , जिसमें बदले में "निजी" चर होते हैं privateVar

लेकिन ये जावास्क्रिप्ट के लिए अधिक विशेष उपयोग के मामले हैं।

एक प्रोग्रामर क्या विशिष्ट कार्य करेगा जो एक बंद द्वारा सबसे अच्छा काम किया जा सकता है?

उसके कई कारण हैं। एक हो सकता है, कि यह उसके लिए स्वाभाविक है, क्योंकि वह एक कार्यात्मक प्रतिमान का पालन करता है । या जावास्क्रिप्ट में: भाषा के कुछ सवालों को दरकिनार करने के लिए बंदियों पर भरोसा करना केवल आवश्यकता है।


"बंद करने का उद्देश्य केवल राज्य को संरक्षित करना है; इसलिए नाम बंद होना - यह राज्य के ऊपर बंद हो जाता है।": यह भाषा पर निर्भर करता है, वास्तव में। बाहरी नाम / चर पर क्लोज़र बंद हो जाते हैं। ये राज्य को निरूपित कर सकते हैं (स्मृति स्थान जिन्हें बदला जा सकता है) लेकिन मूल्यों (अपरिवर्तनीय) को भी निरूपित कर सकते हैं। हास्केल में क्लोजर राज्य को संरक्षित नहीं करते हैं: वे उस जानकारी को संरक्षित करते हैं जो इस समय ज्ञात था और उस संदर्भ में जिसमें क्लोजर बनाया गया था।
जियोर्जियो

1
»वे उस जानकारी को संरक्षित करते हैं जो उस समय ज्ञात थी और जिस संदर्भ में बंद किया गया था« स्वतंत्र रूप से इसे बदला जा सकता है या नहीं, यह राज्य है - शायद अपरिवर्तनीय स्थिति
थॉमस जंक

16

क्लोजर के लिए दो मुख्य उपयोग मामले हैं:

  1. Asynchrony। मान लें कि आप एक ऐसा कार्य करना चाहते हैं जिसमें कुछ समय लगेगा, और तब कुछ करना होगा जब यह पूरा हो जाएगा। आप या तो इसके लिए अपना कोड प्रतीक्षा कर सकते हैं, जो आगे के निष्पादन को अवरुद्ध करता है और आपके कार्यक्रम को अनुत्तरदायी बना सकता है, या अपने कार्य को अतुल्यकालिक रूप से कॉल कर सकता है और कह सकता है "पृष्ठभूमि में यह लंबा कार्य शुरू करें, और जब यह पूरा हो जाए, तो" इस समापन को निष्पादित करें ", जहां बंद होने पर निष्पादित करने के लिए कोड होता है।

  2. कॉलबैक। इन्हें भाषा और मंच के आधार पर "डेलिगेट्स" या "इवेंट हैंडलर" के रूप में भी जाना जाता है। विचार यह है कि आपके पास एक अनुकूलन योग्य वस्तु है, जो कुछ अच्छी तरह से परिभाषित बिंदुओं पर, एक घटना को अंजाम देगी , जो उस कोड द्वारा पारित क्लोजर को चलाता है जो इसे सेट करता है। उदाहरण के लिए, आपके प्रोग्राम के UI में आपके पास एक बटन हो सकता है, और आप इसे एक क्लोजर देते हैं जो कोड को निष्पादित करने के लिए रखता है जब उपयोगकर्ता बटन पर क्लिक करता है।

क्लोजर के लिए कई अन्य उपयोग हैं, लेकिन वे दो मुख्य हैं।


23
तो, मूल रूप से कॉलबैक तब होता है, क्योंकि पहला उदाहरण कॉलबैक भी है।
रॉबर्ट हार्वे

2
@ रोबर्टहवे: तकनीकी रूप से सच है, लेकिन वे अलग-अलग मानसिक मॉडल हैं। उदाहरण के लिए, (आम तौर पर बोलकर) आप इवेंट हैंडलर को कई बार बुलाए जाने की उम्मीद करते हैं, लेकिन आपका एसिंक्स निरंतरता केवल एक बार कहा जाता है। लेकिन हां, तकनीकी रूप से आप जो कुछ भी बंद कर देंगे, वह कॉलबैक है। (जब तक आप इसे एक अभिव्यक्ति पेड़ में परिवर्तित नहीं कर रहे हैं, लेकिन यह पूरी तरह से अलग मामला है।);)
मेसन व्हीलर

4
@ रोबर्टहवे: कॉलबैक के रूप में नज़दीकियों को देखना आपको दिमाग के एक फ्रेम में डाल देता है जो वास्तव में आपको प्रभावी ढंग से उपयोग करने से रोक देगा। स्टेरॉयड पर क्लोजर कॉलबैक हैं।
22 दिसंबर को gnasher729

13
@MasonWheeler इसे इस तरह रखो, यह गलत लगता है। कॉलबैक का क्लोजर से कोई लेना-देना नहीं है; निश्चित रूप से आप किसी फ़ंक्शन को किसी क्लोजर में वापस कॉल कर सकते हैं या कॉलबैक के रूप में एक कॉल को बंद कर सकते हैं; लेकिन कॉलबैक जरूरी नहीं है कि वह बंद हो। एक कॉलबैक सिर्फ एक साधारण फ़ंक्शन कॉल है। एक घटनाचक्र प्रति बंद नहीं है। एक प्रतिनिधि एक बंद आवश्यक नहीं है: यह मुख्य रूप से फ़ंक्शन पॉइंटर्स का C # तरीका है। बेशक आप इसे एक क्लोजर के निर्माण के लिए उपयोग कर सकते हैं। तुम्हारा स्पष्टीकरण अशुद्ध है। बिंदु राज्य के ऊपर बंद हो रहा है और इसका उपयोग कर रहा है।
थॉमस जंक

5
हो सकता है कि यहाँ जेएस-विशिष्ट धारणाएँ चल रही हैं जो मुझे गलत समझ रही हैं, लेकिन यह उत्तर मेरे लिए बिल्कुल गलत लगता है। अतुल्यकालिक या कॉलबैक कुछ भी उपयोग कर सकते हैं जो 'कॉल करने योग्य' है। दोनों में से किसी एक को बंद करने की आवश्यकता नहीं है - एक नियमित कार्य ठीक होगा। इस बीच, एक बंद, जैसा कि कार्यात्मक प्रोग्रामिंग में परिभाषित किया गया है, या जैसा कि पायथन में उपयोग किया गया है, उपयोगी है, जैसा कि थॉमस कहते हैं, क्योंकि यह 'कुछ राज्य', यानी एक चर पर बंद हो जाता है, और एक कार्यक्षेत्र को उस चर के लिए लगातार पहुंच प्रदान करता है मान भले ही फ़ंक्शन को कहा जाता है और कई बार बाहर निकलता है।
जोनाथन हार्टले

13

कुछ अन्य उदाहरण:

सॉर्टिंग
अधिकांश सॉर्ट फ़ंक्शन ऑब्जेक्ट्स की जोड़ी की तुलना करके संचालित होते हैं। कुछ तुलना तकनीक की जरूरत है। एक विशिष्ट ऑपरेटर की तुलना को प्रतिबंधित करने का मतलब है एक अनम्य प्रकार। एक बेहतर तरीका यह है कि तुलना फ़ंक्शन को सॉर्ट फ़ंक्शन के तर्क के रूप में प्राप्त किया जाए। कभी-कभी एक स्टेटलेस तुलनात्मक फ़ंक्शन ठीक काम करता है (जैसे, संख्याओं या नामों की सूची को छांटना), लेकिन क्या होगा यदि तुलना राज्य की आवश्यकता है?

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

यह दृष्टिकोण कई थ्रेड्स को एक साथ रखने के साथ-साथ शहरों की एक ही सूची को दो अलग-अलग स्थानों पर उनकी दूरी के आधार पर रखता है। एक क्लोजर जो स्थान को घेरता है, इस समस्या को हल करता है, और यह एक वैश्विक चर की आवश्यकता से छुटकारा दिलाता है।


यादृच्छिक संख्या
मूल rand()ने कोई तर्क नहीं लिया। छद्म आयामी संख्या जनरेटर को राज्य की आवश्यकता होती है। कुछ (जैसे, मेर्सेन ट्विस्टर) को बहुत सारे राज्य चाहिए। यहां तक ​​कि सरल लेकिन भयानक rand()राज्य की जरूरत है। एक नए यादृच्छिक संख्या जनरेटर पर एक गणित जर्नल पेपर पढ़ें और आप अनिवार्य रूप से वैश्विक चर देखेंगे। यह तकनीक के डेवलपर्स के लिए अच्छा है, कॉल करने वालों के लिए इतना अच्छा नहीं है। उस स्थिति को एक संरचना में एन्क्रिप्ट करना और यादृच्छिक संख्या जनरेटर के लिए संरचना को पारित करना वैश्विक डेटा समस्या का एक तरीका है। यह कई गैर-ओओ भाषाओं में उपयोग किया जाता है ताकि एक यादृच्छिक संख्या जनरेटर रीवेंटेंट बनाया जा सके। एक बंद कॉल करने वाले से उस स्थिति को छुपाता है। एक क्लोजर सरल कॉलिंग सीक्वेंस प्रदान करता है rand()और एनकैप्सुलेटेड स्टेट की पुनर्खरीद करता है।

बस एक PRNG की तुलना में यादृच्छिक संख्या में अधिक है। अधिकांश लोग जो यादृच्छिकता चाहते हैं, वे इसे एक निश्चित तरीके से वितरित करते हैं। मैं 0 से 1 के बीच बेतरतीब ढंग से खींची गई संख्याओं के साथ शुरू करूँगा, या यू (0,1) संक्षेप में। कोई भी PRNG जो 0 और कुछ अधिकतम के बीच पूर्णांक बनाता है; बस विभाजित (एक अस्थायी बिंदु के रूप में) अधिकतम द्वारा यादृच्छिक पूर्णांक। इसे लागू करने का एक सुविधाजनक और सामान्य तरीका एक क्लोजर बनाने के लिए है जो एक क्लोजर (PRNG) और इनपुट के रूप में अधिकतम लेता है। अब हमारे पास यू (0,1) के लिए यादृच्छिक जनरेटर का उपयोग करने के लिए एक सामान्य और आसान है।

यू (0,1) के अलावा कई अन्य वितरण भी हैं। उदाहरण के लिए, एक निश्चित माध्य और मानक विचलन के साथ एक सामान्य वितरण। मेरे द्वारा चलाए गए प्रत्येक सामान्य वितरण जनरेटर एल्गोरिथ्म में U (0,1) जनरेटर का उपयोग होता है। सामान्य जनरेटर बनाने का एक सुविधाजनक और सामान्य तरीका एक क्लोजर बनाना है जो यू (0,1) जनरेटर, माध्य और मानक विचलन को राज्य के रूप में जोड़ता है। यह कम से कम वैचारिक रूप से, एक बंद है जो एक बंद को लेता है जो एक तर्क के रूप में एक बंद होता है।


7

क्लोज़र एक रन () पद्धति को लागू करने वाली वस्तुओं के बराबर है, और इसके विपरीत, वस्तुओं को क्लोजर के साथ अनुकरण किया जा सकता है।

  • क्लोजर का लाभ यह है कि वे आसानी से कहीं भी उपयोग किया जा सकता है आप एक फ़ंक्शन की उम्मीद करते हैं: उर्फ ​​उच्च-ऑर्डर फ़ंक्शन, सरल कॉलबैक (या रणनीति पैटर्न)। आपको तदर्थ क्लोजर बनाने के लिए इंटरफ़ेस / क्लास को परिभाषित करने की आवश्यकता नहीं है।

  • वस्तुओं का लाभ अधिक जटिल इंटरैक्शन की संभावना है: कई तरीके और / या विभिन्न इंटरफेस।

तो, बंद या वस्तुओं का उपयोग करना ज्यादातर शैली का विषय है। यहां उन चीजों का एक उदाहरण है जो बंद करना आसान बनाते हैं लेकिन वस्तुओं के साथ लागू करने में असुविधाजनक हैं:

 (let ((seen))
    (defun register-name (name)
       (pushnew name seen :test #'string=))

    (defun all-names ()
       (copy-seq seen))

    (defun reset-name-registry ()
       (setf seen nil)))

मूल रूप से, आप एक छिपे हुए राज्य को एनकैप्सुलेट करते हैं जो केवल वैश्विक क्लोजर के माध्यम से एक्सेस किया जाता है: आपको किसी भी ऑब्जेक्ट को संदर्भित करने की आवश्यकता नहीं है, केवल तीन फ़ंक्शन द्वारा परिभाषित प्रोटोकॉल का उपयोग करें।


  • मैं इस टिप्पणी को सुपरकैट * से संबोधित करने का उत्तर दे रहा हूं ।

मुझे इस तथ्य पर सुपरकैट की पहली टिप्पणी पर भरोसा है कि कुछ भाषाओं में, वस्तुओं के जीवनकाल को ठीक से नियंत्रित करना संभव है, जबकि बंद करने के लिए एक ही बात सच नहीं है। कचरा एकत्र करने वाली भाषाओं के मामले में, हालांकि, वस्तुओं का जीवनकाल आम तौर पर अप्रभावित होता है, और इस प्रकार एक बंद निर्माण करना संभव होता है जिसे एक गतिशील संदर्भ में कहा जा सकता है जहां इसे नहीं बुलाया जाना चाहिए (एक धारा के बाद बंद होने से पढ़ना) बंद है, उदाहरण के लिए)।

हालांकि, एक नियंत्रण चर पर कब्जा करके इस तरह के दुरुपयोग को रोकने के लिए काफी सरल है जो एक बंद होने के निष्पादन की रक्षा करेगा। अधिक सटीक रूप से, यहाँ मेरे मन में है (सामान्य लिस्प में):

(defun guarded (function)
  (let ((active t))
    (values (lambda (&rest args)
              (when active
                (apply function args)))
            (lambda ()
              (setf active nil)))))

यहां, हम एक फ़ंक्शन डिज़ाइनर लेते हैं functionऔर दो क्लोजर वापस करते हैं, दोनों एक स्थानीय चर का नाम लेते हैं active:

  • पहले एक प्रतिनिधि function, केवल जब activeसच है
  • दूसरा एक सेट actionकरने के लिए nil, उर्फ false

इसके बजाय (when active ...), (assert active)अभिव्यक्ति होना निश्चित रूप से संभव है , जो बंद होने की स्थिति में अपवाद को फेंक सकता है जब इसे नहीं होना चाहिए। इसके अलावा, ध्यान रखें कि असुरक्षित कोड पहले से ही एक अपवाद को फेंक सकता है जब इसे बुरी तरह से उपयोग किया जाता है, इसलिए आपको शायद ही कभी ऐसे आवरण की आवश्यकता होगी।

यहां बताया गया है कि आप इसका उपयोग कैसे करेंगे:

(use-package :metabang-bind) ;; for bind

(defun example (obj1 obj2)
  (bind (((:values f f-deactivator)(guarded (lambda () (do-stuff obj1))))
         ((:values g g-deactivator)(guarded (lambda () (do-thing obj2)))))

    ;; ensure the closure are inactive when we exit
    (unwind-protect
         ;; pass closures to other functions
         (progn
           (do-work f)
           (do-work g))

      ;; cleanup code: deactivate closures
      (funcall f-deactivator)
      (funcall g-deactivator))))

ध्यान दें कि निष्क्रिय बंद होने के साथ-साथ अन्य कार्यों को भी दिया जा सकता है; यहाँ, स्थानीय activeचर fऔर के बीच साझा नहीं किया जाता है g; इसके अलावा active, fकेवल करने के लिए संदर्भित करता है obj1और gकेवल करने के लिए संदर्भित करता है obj2

सुपरकैट द्वारा उल्लेखित अन्य बिंदु यह है कि बंद करने से मेमोरी लीक हो सकती है, लेकिन दुर्भाग्य से, यह कचरा एकत्र किए गए वातावरण में लगभग हर चीज के लिए मामला है। यदि वे उपलब्ध हैं, तो इसे कमजोर बिंदुओं द्वारा हल किया जा सकता है (बंद को स्वयं स्मृति में रखा जा सकता है, लेकिन अन्य संसाधनों के कचरा-संग्रह को नहीं रोकता है)।


1
आमतौर पर लागू होने के रूप में बंद करने का एक नुकसान यह है कि एक बार एक बंद करने के लिए जो विधि के स्थानीय चर में से एक का उपयोग करता है, बाहरी दुनिया के संपर्क में है, बंद को परिभाषित करने वाली विधि उस चर को पढ़ने और लिखने पर नियंत्रण खो सकती है। कोई भी सुविधाजनक तरीका नहीं है, अधिकांश भाषाओं में, एक अल्पकालिक बंद को परिभाषित करने के लिए, इसे एक विधि से पारित करें, और गारंटी दें कि यह एक बार वापस आने वाली विधि को प्राप्त करने के लिए मौजूद नहीं रहेगा और न ही बहु-सूत्रीय भाषाओं में कोई रास्ता है गारंटी है कि एक बंद एक अप्रत्याशित सूत्रण संदर्भ में नहीं चलाया जाएगा।
सुपरकैट

@supercat: ऑब्जेक्टिव-सी और स्विफ्ट पर एक नजर
gnasher729

1
@supercat वही नुकसान राज्यव्यापी वस्तुओं के साथ मौजूद नहीं होगा?
एंड्रेस एफ।

@AndresF।: एक आवरण में एक राज्य वस्तु को एनकैप्सुलेट करना संभव है जो अमान्यता का समर्थन करता है; यदि कोड एक निजी रूप से List<T>(काल्पनिक वर्ग) में रखा जाता है TemporaryMutableListWrapper<T>और बाहर के कोड को उजागर करता है, तो यह सुनिश्चित किया जा सकता है कि यदि यह आवरण को अमान्य कर देता है, तो बाहर के कोड का अब हेरफेर करने का कोई तरीका नहीं होगा List<T>। एक बार जब वे अपने अपेक्षित उद्देश्य को पूरा कर लेते हैं, तो अमान्य होने की अनुमति देने के लिए क्लोज़र डिज़ाइन कर सकते हैं, लेकिन यह शायद ही सुविधाजनक है। क्लोजर कुछ पैटर्न को सुविधाजनक बनाने के लिए मौजूद हैं, और उन्हें संरक्षित करने के लिए आवश्यक प्रयास को नकार दिया जाएगा।
सुपरकाट

1
@coredump: C # में, यदि दो क्लोजर का कोई भी वैरिएबल आम में है, तो एक ही कंपाइलर-जेनरेट ऑब्जेक्ट दोनों को सर्व करेगा, क्योंकि एक क्लोजर द्वारा एक साझा वेरिएबल में किए गए बदलाव को दूसरे द्वारा देखा जाना चाहिए। उस बंटवारे से बचने के लिए आवश्यक होगा कि प्रत्येक क्लोजर का अपना ऑब्जेक्ट हो जो अपने स्वयं के अन-वेरिएबल वैरिएबल के साथ-साथ एक शेयर्ड ऑब्जेक्ट के संदर्भ में भी हो, जो शेयर्ड वैरिएबल को रखता हो। असंभव नहीं है, लेकिन यह सब कुछ धीमा करते हुए, अधिकांश परिवर्तनशील पहुंचों के लिए एक अतिरिक्त स्तर को जोड़ देगा।
सुपरकैट

6

ऐसा कुछ भी नहीं जो पहले से ही नहीं कहा गया है, लेकिन शायद एक सरल उदाहरण है।

यहां मध्यांतर का उपयोग करके एक जावास्क्रिप्ट उदाहरण दिया गया है:

// Example function that logs something to the browser's console after a given delay
function delayedLog(message, delay) {
  // this function will be called when the timer runs out
  var fire = function () {
    console.log(message); // closure magic!
  };

  // set a timeout that'll call fire() after a delay
  setTimeout(fire, delay);
}

यहाँ क्या होता है, जब delayedLog()यह कहा जाता है, तो यह टाइमआउट सेट करने के तुरंत बाद वापस आ जाता है, और टाइमआउट पृष्ठभूमि में टिक जाता है।

लेकिन जब टाइमआउट समाप्त हो जाता है और fire()फ़ंक्शन को कॉल करता है, तो कंसोल प्रदर्शित करेगा messageकि मूल रूप से पारित कर दिया गया था delayedLog(), क्योंकि यह अभी भी fire()बंद होने के माध्यम से उपलब्ध है । आप delayedLog()जितनी बार चाहें कॉल कर सकते हैं, एक अलग संदेश के साथ और हर बार देरी कर सकते हैं, और यह सही काम करेगा।

लेकिन कल्पना कीजिए कि जावास्क्रिप्ट में क्लोजर नहीं हैं।

एक रास्ता setTimeout()अवरुद्ध करना होगा - एक "नींद" फ़ंक्शन की तरह - इसलिए delayedLog()जब तक समय समाप्त नहीं हो जाता है, तब तक गुंजाइश नहीं होती है। लेकिन सब कुछ अवरुद्ध करना बहुत अच्छा नहीं है।

एक अन्य तरीका यह होगा कि messageचर को किसी अन्य दायरे में रखा जाए जो कि delayedLog()स्कोप के चले जाने के बाद सुलभ होगा ।

आप वैश्विक - या कम से कम "ब्रॉड स्कोप्ड" - चर का उपयोग कर सकते हैं, लेकिन आपको यह पता लगाना होगा कि किस समय क्या संदेश जाता है। लेकिन यह सिर्फ एक अनुक्रमिक, फीफो कतार नहीं हो सकता है, क्योंकि आप कोई भी विलंब सेट कर सकते हैं जो आप चाहते हैं। तो यह "प्रथम इन, थर्ड आउट" या कुछ और हो सकता है। इसलिए आपको समयबद्ध फ़ंक्शन को इसकी आवश्यकता वाले चर में बांधने के लिए कुछ अन्य साधनों की आवश्यकता होगी।

आप संदेश के साथ टाइमर "समूहों" को टाइमआउट ऑब्जेक्ट को तुरंत रोक सकते हैं। एक वस्तु का संदर्भ कमोबेश एक ऐसा क्षेत्र है जो चारों ओर चिपक जाता है। तब आपके पास ऑब्जेक्ट के संदर्भ में टाइमर निष्पादित होगा, इसलिए इसे सही संदेश तक पहुंच प्राप्त होगी। लेकिन आपको उस ऑब्जेक्ट को स्टोर करना होगा क्योंकि बिना किसी संदर्भ के यह कचरा इकट्ठा हो जाएगा (बिना बंद हुए, इसका कोई निहित संदर्भ भी नहीं होगा)। और इसके टाइमआउट को निकाल देने के बाद आपको ऑब्जेक्ट को निकालना होगा, अन्यथा यह बस चारों ओर चिपक जाएगा। तो आपको टाइमआउट ऑब्जेक्ट्स की सूची के कुछ प्रकार की आवश्यकता होगी, और समय-समय पर इसे हटाने के लिए "खर्च" वस्तुओं की जांच करें - या ऑब्जेक्ट्स सूची से खुद को जोड़ेंगे और हटाएंगे, और ...

तो ... हाँ, यह सुस्त हो रहा है।

शुक्र है, आपको केवल कुछ चरों को रखने के लिए व्यापक दायरे का उपयोग करने की आवश्यकता नहीं है, या वस्तुओं को कम करने की आवश्यकता नहीं है। क्योंकि जावास्क्रिप्ट बंद है, आपके पास पहले से ही आपकी जरूरत की गुंजाइश है। एक ऐसा स्कोप जो messageआपको जरूरत पड़ने पर वैरिएबल तक पहुंच देता है। और उसके कारण, आप delayedLog()ऊपर की तरह लेखन के साथ दूर हो सकते हैं ।


मुझे कॉल करने में समस्या है कि एक बंद । शायद मैं इसे आकस्मिक रूप से बंद करूंगा । messageके कार्य क्षेत्र में संलग्न है fireऔर इसलिए आगे की कॉल में संदर्भित है; लेकिन यह कहना है कि गलती से ऐसा करता है । तकनीकी रूप से यह बंद है। +1 एनीवे;)
थॉमस जंक

@ThomasJunk मुझे यकीन नहीं है कि मैं काफी फॉलो कर रहा हूं। " गैर- आकस्मिक समापन" कैसे दिखेगा? मैंने आपके makeadderउदाहरण को ऊपर देखा , जो मेरी आंखों के लिए, बहुत समान दिखाई देता है। आप एक "क्यूरेड" फ़ंक्शन लौटाते हैं जो दो के बजाय एक एकल arg लेता है; उसी साधन का उपयोग करते हुए, मैं एक फ़ंक्शन बनाता हूं जो शून्य तर्क लेता है। मैं अभी इसे वापस नहीं करता हूं, लेकिन setTimeoutइसके बजाय इसे पास करता हूं ।
14

»मैं अभी इसे वापस नहीं करता हूं« शायद, यही वह बिंदु है, जो मेरे लिए अंतर बनाता है। मैं अपनी "चिंता" को बहुत स्पष्ट नहीं कर सकता;) तकनीकी शब्दों में आप 100% सही हैं। संदर्भित messageमें fireबंद उत्पन्न करता है। और जब इसे बुलाया जाता है तो setTimeoutयह संरक्षित अवस्था का उपयोग करता है।
थॉमस जंक

1
@ThomasJunk मैं देख रहा हूँ कि कैसे यह थोड़ा अलग हो सकता है। मैं आपकी चिंता को साझा नहीं कर सकता, हालांकि :) या, किसी भी दर पर, मैं इसे "आकस्मिक" नहीं कहूंगा - बहुत यकीन है कि मैंने इसे इस तरह से कोडित किया है;)
फ्लेम्बिनो

3

एक अलग भाषा में वास्तविक उदाहरण दिखाने के लिए PHP का उपयोग किया जा सकता है।

protected function registerRoutes($dic)
{
  $router = $dic['router'];

  $router->map(['GET','OPTIONS'],'/api/users',function($request,$response) use ($dic)
  {
    $controller = $dic['user_api_controller'];
    return $controller->findAllAction($request,$response);
  })->setName('api_users');
}

इसलिए मूल रूप से मैं एक फ़ंक्शन पंजीकृत कर रहा हूं जिसे / api / उपयोगकर्ताओं URI के लिए निष्पादित किया जाएगा । यह वास्तव में एक मिडलवेयर फंक्शन है जो कि स्टैक पर स्टोर किया जा रहा है। अन्य कार्यों को इसके चारों ओर लपेटा जाएगा। बहुत पसंद है Node.js / Express.js करता है।

निर्भरता इंजेक्शन कंटेनर जब यह कहा जाता हो जाता है समारोह के अंदर (उपयोग खंड के माध्यम से) उपलब्ध है। कुछ प्रकार के मार्ग एक्शन क्लास बनाना संभव है, लेकिन यह कोड सरल, तेज और बनाए रखने में आसान है।


-1

एक बंद मनमाना कोड का एक टुकड़ा है, जिसमें चर भी शामिल हैं, जिन्हें प्रथम श्रेणी के डेटा के रूप में संभाला जा सकता है।

एक तुच्छ उदाहरण अच्छा पुराना qsort है: यह डेटा को सॉर्ट करने के लिए एक फ़ंक्शन है। आपको इसे एक फ़ंक्शन को पॉइंटर देना होगा जो दो ऑब्जेक्ट्स की तुलना करता है। इसलिए आपको एक फंक्शन लिखना होगा। उस फ़ंक्शन को पैरामीटर करने की आवश्यकता हो सकती है, जिसका अर्थ है कि आप इसे स्थिर चर देते हैं। इसका मतलब है कि यह सुरक्षित नहीं है। आप डीएस में हैं। तो आप एक विकल्प लिखते हैं जो फ़ंक्शन पॉइंटर के बजाय एक क्लोजर लेता है। आप तुरन्त पैरामीटर की समस्या को हल करते हैं क्योंकि पैरामीटर क्लोजर का हिस्सा बन जाते हैं। आप अपने कोड को अधिक पठनीय बनाते हैं क्योंकि आप लिखते हैं कि वस्तुओं की तुलना उस कोड से सीधे कैसे की जाती है जो सॉर्टिंग फ़ंक्शन को कॉल करते हैं।

ऐसी कई स्थितियाँ हैं जहाँ आप कुछ कार्रवाई करना चाहते हैं जिसके लिए बॉयलर प्लेट कोड के एक अच्छे सौदे की आवश्यकता होती है, साथ ही एक छोटे लेकिन आवश्यक कोड के टुकड़े को अनुकूलित करने की आवश्यकता होती है। आप एक बार एक फ़ंक्शन लिखकर बॉयलरप्लेट कोड से बचते हैं जो एक क्लोजर पैरामीटर लेता है और इसके चारों ओर सभी बॉयलरप्लेट कोड करता है, और फिर आप इस फ़ंक्शन को कॉल कर सकते हैं और कोड को एक क्लोजर के रूप में अनुकूलित किया जा सकता है। कोड लिखने के लिए एक बहुत ही कॉम्पैक्ट और पठनीय तरीका।

आपके पास एक फ़ंक्शन है जहां कुछ गैर-तुच्छ कोड को कई अलग-अलग स्थितियों में निष्पादित करने की आवश्यकता होती है। यह या तो कोड दोहराव या विपरीत कोड का उत्पादन करता था ताकि गैर-तुच्छ कोड केवल एक बार मौजूद हो। तुच्छ: आप एक चर के लिए एक बंद असाइन करते हैं और इसे जहां कहीं भी आवश्यक हो, सबसे स्पष्ट तरीके से कहते हैं।

मल्टीथ्रेडिंग: iOS / MacOS X में "बैकग्राउंड थ्रेड पर इस क्लोजर को परफॉर्म करना", "... मेन थ्रेड पर", "... मेन थ्रेड पर, अब से 10 सेकंड" जैसे काम करने हैं। यह मल्टीथ्रेडिंग को तुच्छ बनाता है

अतुल्यकालिक कॉल: यही ओपी ने देखा। कोई भी कॉल जो इंटरनेट तक पहुंचता है, या कुछ और जो समय ले सकता है (जैसे जीपीएस निर्देशांक पढ़ना) कुछ ऐसा है जहां आप परिणाम के लिए इंतजार नहीं कर सकते। इसलिए आपके पास फ़ंक्शन हैं जो पृष्ठभूमि में चीजें करते हैं, और फिर आप उन्हें यह बताने के लिए एक पास पास करते हैं कि जब वे समाप्त हो जाते हैं तो क्या करें।

यह एक छोटी शुरुआत है। पाँच परिस्थितियाँ जहाँ क्लोजर कॉम्पैक्ट, पठनीय, रिलेवेंट और कुशल कोड के उत्पादन के मामले में क्रांतिकारी हैं।


-4

एक बंद एक विधि लिखने का एक छोटा तरीका है जहां इसका उपयोग किया जाना है। यह आपको एक अलग विधि घोषित करने और लिखने के प्रयास को बचाता है। यह उपयोगी है जब विधि केवल एक बार उपयोग की जाएगी और विधि की परिभाषा कम है। लाभ टाइपिंग कम हो जाते हैं क्योंकि फ़ंक्शन का नाम, इसकी वापसी प्रकार या इसके एक्सेस संशोधक को निर्दिष्ट करने की कोई आवश्यकता नहीं है। इसके अलावा, कोड को पढ़ते समय आपको विधि की परिभाषा के लिए कहीं और नहीं देखना होगा।

उपरोक्त डैन एवेदर द्वारा अंडरस्टैंड लैंबडा एक्सप्रेशंस का सारांश है।

इसने मेरे लिए क्लोजर के उपयोग को स्पष्ट किया क्योंकि यह विकल्प (क्लोजर बनाम विधि) और प्रत्येक के लाभों को स्पष्ट करता है।

निम्न कोड का उपयोग एक बार किया जाता है, और केवल एक बार सेटअप के दौरान। ViewDidLoad के तहत इसे जगह में लिखने से इसे कहीं और खोजने में परेशानी होती है, और कोड का आकार छोटा हो जाता है।

myPhoton!.getVariable("Temp", completion: { (result:AnyObject!, error:NSError!) -> Void in
  if let e = error {
    self.getTempLabel.text = "Failed reading temp"
  } else {
    if let res = result as? Float {
    self.getTempLabel.text = "Temperature is \(res) degrees"
    }
  }
})

इसके अलावा, यह कार्यक्रम के अन्य हिस्सों को अवरुद्ध किए बिना एक अतुल्यकालिक प्रक्रिया को पूरा करने के लिए प्रदान करता है, और, एक बंद बाद के फ़ंक्शन कॉल में पुन: उपयोग के लिए एक मूल्य बनाए रखेगा।

एक और बंद; यह एक मूल्य पकड़ता है ...

let animals = ["fish", "cat", "chicken", "dog"]
let sortedStrings = animals.sorted({ (one: String, two: String) -> Bool in return one > two
}) println(sortedStrings)

4
दुर्भाग्य से, यह बंद और लंबोदर को भ्रमित करता है। लैम्ब्डा अक्सर क्लोजर का उपयोग करते हैं, क्योंकि वे आम तौर पर कहीं अधिक उपयोगी होते हैं यदि परिभाषित किया गया है) एक बहुत ही कठिन और बी) के भीतर और चर सहित किसी दिए गए विधि संदर्भ पर निर्भर करता है। हालांकि, वास्तविक बंद का लंबोदर के विचार से कोई लेना-देना नहीं है, जो मूल रूप से एक प्रथम श्रेणी के कार्य को परिभाषित करने और बाद में उपयोग करने के लिए पास करने की क्षमता है।
नाथन तुग्गी

जब आप इस उत्तर को वोट कर रहे हैं, तो इसे पढ़ें ... मुझे कब वोट देना चाहिए? जब भी आपका सामना करना पड़ता है, तो अपने डाउनवोट का उपयोग करें, उदाहरण के लिए, मैला-कुचैला, कोई प्रयास-रहित पोस्ट, या ऐसा उत्तर जो स्पष्ट रूप से और शायद खतरनाक रूप से गलत हो। मेरे जवाब में बंद करने के उपयोग के कुछ कारणों की कमी हो सकती है, लेकिन यह न तो उदासीन रूप से मैला है और न ही खतरनाक रूप से गलत है। कार्यात्मक प्रोग्रामिंग और लैम्ब्डा संकेतन पर उस केंद्र को बंद करने के कई कागजात और चर्चाएं हैं। मेरा सभी उत्तर कहता है कि कार्यात्मक प्रोग्रामिंग के इस स्पष्टीकरण ने मुझे क्लोजर को समझने में मदद की। वह और लगातार मूल्य।
बेंड्रिक्स

1
उत्तर शायद खतरनाक नहीं है , लेकिन यह निश्चित रूप से "स्पष्ट रूप से [...] गलत है।" यह उन अवधारणाओं के लिए गलत शब्दों का उपयोग करता है जो अत्यधिक पूरक हैं और इस प्रकार अक्सर एक साथ उपयोग किए जाते हैं - बिल्कुल जहां अंतर की स्पष्टता आवश्यक है। यह प्रोग्रामर के लिए डिज़ाइन की समस्याओं के कारण होने की संभावना है जो इसे पढ़ता है यदि वह बिना पढ़े छोड़ दिया जाए। (और जब से मैं बता सकता हूं, कोड उदाहरण में बस कोई क्लोजर नहीं होता है, केवल एक लंबो फ़ंक्शन होता है, यह समझाने में मदद नहीं करता है कि क्लोजर मददगार क्यों होगा।)
नाथन तुग्गी

नाथन, कि कोड उदाहरण स्विफ्ट में एक बंद है। आप किसी और से पूछ सकते हैं यदि आप मुझ पर संदेह करते हैं। तो, अगर यह एक बंद है, तो क्या आप इसे वोट देंगे?
बेंड्रिक्स

1
Apple काफी स्पष्ट रूप से वर्णन करता है कि उनके प्रलेखन में बंद होने का क्या मतलब है । "क्लोज़र कार्यक्षमता के स्व-निहित ब्लॉक हैं जिन्हें आपके कोड में पास और उपयोग किया जा सकता है। स्विफ्ट में क्लोज़र सी और ऑब्जेक्टिव-सी में ब्लॉक और अन्य प्रोग्रामिंग भाषाओं में लैम्ब्डा के समान हैं।" जब आप कार्यान्वयन और शब्दावली के लिए आते हैं तो यह भ्रामक हो सकता है
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.