কোনও প্রোগ্রাম কেন ক্লোজার ব্যবহার করবে?


58

ক্লোজারগুলি ব্যাখ্যা করে অনেকগুলি পোস্ট পড়ার পরেও আমি এখনও একটি মূল ধারণাটি অনুপস্থিত: কেন বন্ধ লিখবেন? কোনও প্রোগ্রামার কোন সুনির্দিষ্ট কাজটি সম্পাদন করবেন যা বন্ধের মাধ্যমে সেরা পরিবেশিত হতে পারে?

সুইফটে ক্লোজারগুলির উদাহরণ হ'ল এনএসইউআরএল এর প্রবেশাধিকার এবং বিপরীত জিওকোডার ব্যবহার। এখানে যেমন একটি উদাহরণ। দুর্ভাগ্যক্রমে, এই কোর্সগুলি কেবল বন্ধের উপস্থাপন করে; কোড সমাধানটি বন্ধ হিসাবে কেন লেখা হয়েছে তা তারা ব্যাখ্যা করে না।

একটি বাস্তব বিশ্ব প্রোগ্রামিং সমস্যার একটি উদাহরণ যা আমার মস্তিষ্ককে এই বলে বলতে উদ্বুদ্ধ করতে পারে যে, "আহা, এর জন্য আমার একটি ক্লোজ লেখা উচিত", তাত্ত্বিক আলোচনার চেয়ে বেশি তথ্যবহুল হতে পারে। এই সাইটে তাত্ত্বিক আলোচনার কোনও ঘাটতি নেই।


7
"এখানে বন্ধের বিস্তৃত বিবরণ পর্যালোচনা" - আপনি কি একটি লিঙ্ক মিস করছেন?
ড্যান পিচেলম্যান

2
প্রাসঙ্গিক উত্তরের নীচে আপনার একটি মন্তব্য, অ্যাসিক্রোনাস টাস্ক সম্পর্কে সেই ব্যাখ্যাটি রাখা উচিত । এটি আপনার মূল প্রশ্নের অংশ নয় এবং উত্তরদাতা আপনার সম্পাদনা সম্পর্কে কখনই অবহিত হবে না।
রবার্ট হার্ভে

5
কেবল একটি জালিয়াতি: ক্লোজারগুলির গুরুত্বপূর্ণ পয়েন্টটি হ'ল লেক্সিকাল স্কোপিং (ডাইনামিক স্কোপিংয়ের বিপরীতে), লেক্সিকাল স্কোপিং ছাড়া ক্লোজারগুলি কৃপণাহীন are বন্ধগুলি কখনও কখনও লেক্সিকাল ক্লোজার বলে ures
হফম্যান

1
বন্ধগুলি আপনাকে ফাংশনগুলি ইনস্ট্যান্ট করার অনুমতি দেয় ।
ব্যবহারকারী 253751

1
ফাংশনাল প্রোগ্রামিং সম্পর্কিত যে কোনও ভাল বই পড়ুন। সম্ভবত এসআইসিপি
বেসিল স্টারিনকিভিচ

উত্তর:


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);

আপনার নিজস্ব কোডে, এমন স্থানগুলির সন্ধান করুন যেখানে আপনি কেবল অস্থায়ী মানগুলি এক জায়গা থেকে অন্য জায়গায় যোগাযোগ করার জন্য প্রচুর বয়লারপ্লেট উত্পন্ন করেন। ক্লোজার দিয়ে প্রতিস্থাপন বিবেচনা করার জন্য এগুলি দুর্দান্ত সুযোগ।


বন্ধ কিভাবে সংঘবদ্ধতা হ্রাস করতে পারে?
এসবিচেনকো

ক্লোজার ছাড়াই, আপনাকে ডেটাতে যোগাযোগ করতে সক্ষম হওয়ার জন্য আপনাকে 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 চলকটির অ্যাক্সেস ধরে রাখে ।totalrenderInt

জাভাস্ক্রিপ্টের চেয়ে আরও traditionতিহ্যগতভাবে বস্তু-কেন্দ্রিক ভাষায়, আপনি এই ক্লাসটি লিখতে পারতেন যাতে এই মোট চলক থাকে এবং একটি ক্লোজার তৈরির পরিবর্তে পাশ করতে পারে। তবে একটি বন্ধন এটি করার অনেক বেশি শক্তিশালী, পরিষ্কার এবং মার্জিত উপায়।

আরও পড়া


10
সাধারণভাবে, আপনি বলতে পারেন যে "প্রথম শ্রেণির ফাংশন == কেবলমাত্র একটি পদ্ধতিযুক্ত অবজেক্ট", "বন্ধকরণ == কেবলমাত্র একটি পদ্ধতি এবং রাষ্ট্রের সাথে অবজেক্ট", "অবজেক্ট == ক্লোজারের বান্ডিল"।
Jörg ডব্লু মিটাগ

ভাল লাগছে। আরেকটা জিনিস, এবং এই পণ্ডিতিপনা হতে পারে, যে জাভাস্ক্রিপ্ট হয় হয় অবজেক্ট-মুখী, এবং আপনি পারে একটি বস্তু যে মোট পরিবর্তনশীল রয়েছে তৈরি এবং প্রায় পাস। বন্ধগুলি আরও বেশি শক্তিশালী, পরিষ্কার এবং মার্জিত হয়ে থাকে এবং আরও অনেকটা মূর্খ জাভাস্ক্রিপ্ট তৈরি করে, তবে এটি যেভাবে রচিত হয়েছে তা বোঝাতে পারে যে জাভাস্ক্রিপ্ট কোনও বস্তু-কেন্দ্রিক উপায়ে এটি করতে পারে না।
কেআরয়ান

2
আসলে, সত্যিকারের পেডেন্টিক হতে : ক্লোজারগুলি হ'ল জাভাস্ক্রিপ্টকে প্রথম স্থানে অবজেক্ট-ওরিয়েন্টড করে তোলে! ওও ডেটা বিমূর্তি সম্পর্কে, এবং ক্লোজারগুলি জাভাস্ক্রিপ্টে ডেটা বিমূর্তি সম্পাদনের উপায়।
Jörg ডব্লু মিটাগ

@ জার্গডব্লিউমিত্যাগ: আপনি যেমন কেবল একটি পদ্ধতিতে ক্লোয়ার্সকে অবজেক্ট হিসাবে দেখতে পাচ্ছেন, আপনি একই ভেরিয়েবলের কাছাকাছি ক্লোজারগুলির সংগ্রহ হিসাবে অবজেক্টগুলি দেখতে পাচ্ছেন: কোনও অবজেক্টের সদস্য ভেরিয়েবলগুলি কেবলমাত্র অবজেক্টের কনস্ট্রাক্টরের স্থানীয় ভেরিয়েবল এবং অবজেক্টের পদ্ধতিগুলি কনস্ট্রাক্টরের স্কোপের অভ্যন্তরে ক্লোজারগুলি সংজ্ঞায়িত করা হয় এবং পরে ডাকার জন্য উপলব্ধ করা হয়। কনস্ট্রাক্টর ফাংশন একটি উচ্চ-অর্ডার ফাংশন (অবজেক্ট) প্রদান করে যা প্রার্থনার জন্য ব্যবহৃত পদ্ধতিটির নাম অনুসারে প্রতিটি বন্ধে প্রেরণ করতে পারে।
জর্জিও

@ জর্জিও: প্রকৃতপক্ষে, স্কিমে সাধারণত বস্তুগুলি কীভাবে প্রয়োগ করা হয়, উদাহরণস্বরূপ, এবং এটি বাস্তবে কীভাবে জাভাস্ক্রিপ্টে অবজেক্টগুলি প্রয়োগ করা হয় (স্কিমের সাথে তার ঘনিষ্ঠ সম্পর্কের কথা বিবেচনা করে অবাক হওয়ার কিছু নেই, সর্বোপরি, ব্রেন্ডন আইচ মূলত একটি নকশা তৈরির জন্য নিয়োগ করা হয়েছিল নেটস্কেপ নেভিগেটরের অভ্যন্তরে একটি এম্বেডড স্কিম ইন্টারপ্রেটারকে স্কিম উপভাষা এবং প্রয়োগ করে এবং কেবলমাত্র পরে "সি ++ এর মতো দেখতে এমন অবজেক্টগুলির সাথে একটি ভাষা তৈরি করার আদেশ দেওয়া হয়েছিল যার পরে তিনি সেই বিপণনের প্রয়োজনীয়তাগুলি মেনে চলার জন্য সর্বনিম্ন পরিমাণে পরিবর্তন করেছিলেন"।
Jörg ডব্লু মিটাগ

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){}{} .Further আপনি সংজ্ঞায়িত (implicitely) অন্য ফাংশন add5উচ্চতর ক্রম funtion কলিং ফলে 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"))));

আর একটি সাধারণ ব্যবহারের নাম হ'ল তথাকথিত IIFE = অবিলম্বে অনুরোধ করা ফাংশন এক্সপ্রেশন। এটি জাভাস্ক্রিপ্টে জাল ব্যক্তিগত সদস্যের ভেরিয়েবলগুলিতে খুব সাধারণ । এটি একটি ফাংশনের মাধ্যমে করা হয়, যা একটি ব্যক্তিগত সুযোগ তৈরি করে = closure, কারণ এটি সংজ্ঞা দেওয়ার পরে তা তাত্ক্ষণিকভাবে হয়। কাঠামোটি হ'ল function(){}()()সংজ্ঞা পরে বন্ধনী লক্ষ্য করুন । এটি প্রকাশের মডিউল প্যাটার্ন সহ অবজেক্ট-তৈরির জন্য এটি ব্যবহার সম্ভব করে তোলে । কৌতুকটি একটি সুযোগ তৈরি করছে এবং একটি অবজেক্ট ফিরিয়ে দিচ্ছে, যা আইআইএফই কার্যকর করার পরে এই সুযোগে অ্যাক্সেস পেয়েছে।

আদির উদাহরণটি এরকম দেখাচ্ছে:

 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
»তারা এমন তথ্য সংরক্ষণ করে যা এই মুহূর্তে এবং যে প্রসঙ্গে বন্ধের সৃজন হয়েছিল known স্বতন্ত্রভাবে এটি পরিবর্তন করা যায় কি না, এটি রাষ্ট্র - সম্ভবত অপরিবর্তনীয় রাষ্ট্র
থমাস

16

বন্ধের জন্য দুটি প্রধান ব্যবহারের মামলা রয়েছে:

  1. Asynchrony। আসুন আমরা বলি যে আপনি এমন কোনও কাজ সম্পাদন করতে চান যা কিছুটা সময় নেয় এবং তারপরে কিছু শেষ হয়ে যায়। হয় আপনি আপনার কোডটি এটি হয়ে যাওয়ার জন্য অপেক্ষা করতে পারেন, যা আরও কার্যকর করা অবরুদ্ধ করে এবং আপনার প্রোগ্রামটিকে প্রতিক্রিয়াহীন করে তুলতে পারে বা আপনার কার্যকে সংবিধানে কল করতে পারে এবং "ব্যাকগ্রাউন্ডে এই দীর্ঘ কাজটি শুরু করুন, এবং এটি শেষ হলে, এই বন্ধকরণ কার্যকর করুন", যেখানে ক্লোজারে কোডটি শেষ হয়ে গেলে তা কার্যকর করতে হবে।

  2. Callbacks। এগুলি ভাষা এবং প্ল্যাটফর্মের উপর নির্ভর করে "প্রতিনিধি" বা "ইভেন্ট হ্যান্ডলার" হিসাবেও পরিচিত। ধারণাটি হ'ল আপনার একটি কাস্টমাইজযোগ্য অবজেক্ট রয়েছে যা কিছু নির্দিষ্ট সংজ্ঞায়িত পয়েন্টগুলিতে একটি ইভেন্ট কার্যকর করবে , যা কোড সেট করে সেট আপ করে এমন একটি ক্লোজার চালায়। উদাহরণস্বরূপ, আপনার প্রোগ্রামের ইউআইতে আপনার কাছে একটি বোতাম থাকতে পারে এবং ব্যবহারকারী যখন বোতামে ক্লিক করেন তখন সম্পাদন করার কোডটি ধারণ করে আপনি এটি একটি ক্লোজার দেন।

বন্ধের জন্য অন্যান্য বেশ কয়েকটি ব্যবহার রয়েছে তবে এটি দুটি প্রধান main


23
সুতরাং, প্রাথমিকভাবে কলব্যাকস, কারণ প্রথম উদাহরণটিও একটি কলব্যাক also
রবার্ট হার্ভে

2
@ রবার্টহারভে: প্রযুক্তিগতভাবে সত্য, তবে তারা বিভিন্ন মানসিক মডেল। উদাহরণস্বরূপ, (সাধারণভাবে বলতে গেলে) আপনি ইভেন্ট হ্যান্ডলারটি একাধিকবার কল করার প্রত্যাশা করছেন, তবে আপনার অ্যাসিঙ্ক ধারাবাহিকতা কেবল একবার ডাকা হবে। তবে হ্যাঁ, প্রযুক্তিগতভাবে আপনি বন্ধের সাথে যা কিছু করেছিলেন তা কলব্যাক। (যদি আপনি এটিকে একটি এক্সপ্রেশন ট্রি তে রূপান্তর না করেন তবে এটি সম্পূর্ণ আলাদা বিষয়));)
ম্যাসন হুইলারের

4
@ রবার্টহারভে: কলব্যাক হিসাবে ক্লোজারগুলি দেখার ফলে আপনি মনের এমন একটি ফ্রেমে পৌঁছান যা আপনাকে কার্যকরভাবে কার্যকরভাবে ব্যবহার করা থেকে বিরত করবে। ক্লোজারগুলি স্টেরয়েডগুলির কলব্যাক।
gnasher729

13
@ ম্যাসনওহেলার এইভাবে রাখুন, এটি ভুল বলে মনে হচ্ছে। কলব্যাক্স বন্ধ হওয়ার সাথে কিছু করার নেই; অবশ্যই আপনি একটি বন্ধের মধ্যে একটি ফাংশন কল করতে পারেন বা কলব্যাক হিসাবে একটি ক্লোজর কল করতে পারেন; তবে কলব্যাক বন্ধ হওয়ার দরকার নেই। একটি কলব্যাক কেবল একটি সাধারণ ফাংশন কল। কোনও ইভেন্ট হ্যান্ডলার কোনও বন্ধের জন্য নয়। কোনও প্রতিনিধি কোনও বন্ধের প্রয়োজন হয় না: এটি মূলত সি # ফাংশন পয়েন্টারগুলির উপায়। অবশ্যই আপনি এটি নির্মাণ বন্ধ করতে ব্যবহার করতে পারেন। আপনার ব্যাখ্যা অনর্থক। পয়েন্টটি রাষ্ট্রের উপর দিয়ে বন্ধ হয়ে যাচ্ছে এবং এটির ব্যবহার করছে।
টমাস

5
এখানে এখানে জেএস-নির্দিষ্ট ধারণাটি চলছে যা আমাকে ভুল বোঝাবুঝি করছে, তবে এই উত্তরটি আমার কাছে একেবারেই ভুল বলে মনে হচ্ছে। অ্যাসিঙ্ক্রোনি বা কলব্যাকগুলি 'কলযোগ্য' এমন কোনও কিছু ব্যবহার করতে পারে। তাদের উভয়ের জন্য একটি বন্ধের প্রয়োজন নেই - একটি নিয়মিত কাজ ভাল করবে। এদিকে, থমাস বলেছে যেহেতু ফাংশনাল প্রোগ্রামিংয়ে সংজ্ঞায়িত বা পাইথনে ব্যবহৃত হিসাবে একটি বন্ধন কার্যকর, কারণ এটি কিছু রাজ্য, অর্থাৎ একটি ভেরিয়েবল 'বন্ধ করে' দেয় এবং অভ্যন্তরীণ সুযোগে কোনও ক্রিয়াকলাপকে সেই ভেরিয়েবলের সাথে ধারাবাহিক অ্যাক্সেস দেয় gives এমনকি যদি ফাংশনটি ডাকা হয় এবং বহুবার প্রস্থান হয় value
জোনাথন হার্টলি

13

অন্যান্য কয়েকটি উদাহরণ:

বাছাই
সর্বাধিক বাছাই করা ফাংশনগুলি বস্তুর জোড়া তুলনা করে কাজ করে। কিছু তুলনা কৌশল প্রয়োজন। একটি নির্দিষ্ট অপারেটরের সাথে তুলনা সীমাবদ্ধ করার অর্থ একটি বরং জটিলতর বাছাই করা। একটি আরও ভাল পদ্ধতির বাছাই ফাংশন যুক্তি হিসাবে তুলনা ফাংশন প্রাপ্ত হয়। কখনও কখনও একটি রাষ্ট্রবিহীন তুলনা ফাংশন সূক্ষ্মভাবে কাজ করে (উদাহরণস্বরূপ, সংখ্যা বা নামের একটি তালিকা বাছাই), তবে কি যদি তুলনা রাষ্ট্রের প্রয়োজন?

উদাহরণস্বরূপ, কিছু নির্দিষ্ট স্থানে দূরত্বে শহরগুলির তালিকা বাছাই করার বিষয়টি বিবেচনা করুন। একটি কুরুচিপূর্ণ সমাধান হ'ল সেই অবস্থানটির স্থানাঙ্কগুলি একটি বৈশ্বিক চলকগুলিতে সঞ্চয় করা। এটি তুলনা ফাংশনটি নিজেকে রাষ্ট্রহীন করে তোলে তবে বৈশ্বিক পরিবর্তনশীলের ব্যয় করে।

এই পদ্ধতির একাধিক থ্রেড একই সাথে একই তালিকার দু'টি পৃথক স্থানে একই শহরগুলির তালিকা বাছাই করা থেকে বিরত রয়েছে। কোনও অবস্থান বন্ধ করে দেওয়া এই সমস্যাটি সমাধান করে এবং এটি একটি বৈশ্বিক পরিবর্তনশীলের প্রয়োজনীয়তা থেকে মুক্তি পায়।


এলোমেলো সংখ্যাগুলি
আসল rand()কোনও আর্গুমেন্ট নেয় নি। সিউডোরডম নম্বর জেনারেটরের রাষ্ট্র দরকার। কিছু (যেমন, মের্সেন টুইস্টার) এর প্রচুর রাজ্যের প্রয়োজন। এমনকি সহজ তবে ভয়ানক rand()প্রয়োজনীয় রাষ্ট্র। নতুন এলোমেলো সংখ্যার জেনারেটরে গণিতের জার্নাল পেপারটি পড়ুন এবং আপনি অনিবার্যভাবে বিশ্বব্যাপী ভেরিয়েবলগুলি দেখতে পাবেন। কৌশলটির বিকাশকারীদের পক্ষে এটি দুর্দান্ত, কলকারীদের পক্ষে এত সুন্দর নয়। একটি স্ট্রাকচারের মধ্যে সেই রাষ্ট্রকে আবদ্ধ করা এবং কাঠামোটি এলোমেলো সংখ্যা জেনারেটরের কাছে পাস করা বিশ্বব্যাপী ডেটা সমস্যার প্রায় এক উপায়। এলোমেলো সংখ্যার জেনারেটরকে পুনরায় ভাড়া দেওয়ার জন্য অনেক অ-ও ভাষায় এই পদ্ধতির ব্যবহার। একটি বন্ধক কলার থেকে সেই রাজ্যটি লুকিয়ে রাখে। একটি ক্লোজার সহজ কলিং সিকোয়েন্স rand()এবং এনক্যাপসুলেটেড স্টেটের পুনরায় প্রবর্তন করে।

কেবলমাত্র একটি পিআরএনজি ছাড়াও এলোমেলো সংখ্যা রয়েছে। বেশিরভাগ মানুষ যারা এলোমেলোভাবে চান এটি এটি একটি নির্দিষ্ট উপায়ে বিতরণ করতে চায়। আমি 0 এবং 1 এর মধ্যে এলোমেলোভাবে অঙ্কিত সংখ্যাগুলি বা সংক্ষেপে ইউ (0,1) দিয়ে শুরু করব। কোনও PRNG যা 0 এবং কিছু সর্বাধিকের মধ্যে পূর্ণসংখ্যা উত্পন্ন করে তা করবে; সর্বাধিক দ্বারা এলোমেলো পূর্ণসংখ্যার (এক ভাসমান বিন্দু হিসাবে) ভাগ করুন এটি কার্যকর করার জন্য একটি সুবিধাজনক এবং জেনেরিক উপায় হ'ল একটি ক্লোরেশন তৈরি করা যা বন্ধ হয় (পিআরএনজি) এবং সর্বাধিক ইনপুট হিসাবে। এখন আমাদের কাছে জেনেরিক এবং ইউ (0,1) এর জন্য এলোমেলো জেনারেটর ব্যবহার করা সহজ।

ইউ (0,1) ছাড়াও আরও অনেকগুলি বিতরণ রয়েছে। উদাহরণস্বরূপ, নির্দিষ্ট গড় এবং মানক বিচ্যুতি সহ একটি সাধারণ বিতরণ। প্রতিটি সাধারণ বিতরণ জেনারেটর অ্যালগরিদম আমি জুড়ে চলেছি একটি ইউ (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
সাধারণত প্রয়োগ করা হিসাবে ক্লোজারগুলির একটি অসুবিধা হ'ল একবার যদি কোনও পদ্ধতির স্থানীয় ভেরিয়েবল ব্যবহার করে এমন এক ক্লোজারটি বাইরের বিশ্বের কাছে প্রকাশিত হয় তবে সেই পরিবর্তনশীলটি পড়তে এবং লিখিতভাবে ক্লোজারটিকে সংজ্ঞায়িত করার পদ্ধতিটি নিয়ন্ত্রণ হারিয়ে ফেলতে পারে। একাধিক ভাষায় সাময়িক বন্ধের সংজ্ঞা দেওয়ার জন্য, কোনও পদ্ধতিতে এটি পাঠানোর কোনও সুবিধাজনক উপায় নেই এবং গ্যারান্টি দেওয়া হয়েছে যে পদ্ধতিটি ফিরে আসার পরে এটি পুনরায় বন্ধ হয়ে যাবে এবং মাল্টি-থ্রেডেড ভাষায় কোনও উপায় নেই গ্যারান্টি দিন যে কোনও বন্ধ অপ্রত্যাশিত থ্রেডিং প্রসঙ্গে চালানো হবে না।
সুপারক্যাট

@ সুপের্যাট: অবজেক্টিভ-সি এবং সুইফটটি দেখুন।
gnasher729

1
@ সুপের্যাট রাষ্ট্রীয় বস্তুগুলির সাথে কি একই অসুবিধে থাকবে না?
আন্দ্রেস এফ।

@ অ্যান্ড্রেসএফ: অবৈধকরণকে সমর্থন করে এমন একটি মোড়কে একটি রাষ্ট্রীয় বস্তু আবদ্ধ করা সম্ভব; যদি কোডটি List<T>একটি (অনুমানমূলক শ্রেণিতে) ব্যক্তিগতভাবে অনুষ্ঠিত একটি encapsulates TemporaryMutableListWrapper<T>এবং বাইরের কোডে প্রকাশ করে, এটি নিশ্চিত করা যেতে পারে যে এটি যদি মোড়কে অবৈধ করে দেয় তবে বাইরের কোডটি আর ম্যানিপুলেট করার কোনও উপায় থাকবে না List<T>। একবার তাদের প্রত্যাশিত উদ্দেশ্যটি সম্পাদন করার পরে অবৈধতার অনুমতি দেওয়ার জন্য ক্লোজারগুলি ডিজাইন করতে পারেন তবে এটি খুব সহজেই সুবিধাজনক। নির্দিষ্ট নিদর্শনগুলিকে সুবিধাজনক করার জন্য বন্ধ রয়েছে এবং তাদের রক্ষা করার জন্য প্রয়োজনীয় প্রচেষ্টা এটিকে অস্বীকার করবে।
সুপারক্যাট

1
@ কর্ডাম্প: সি # তে, দুটি ক্লোজারের যদি কোনও ভেরিয়েবল অভিন্ন হয় তবে একই সংকলক-উত্পাদিত বস্তু উভয়কেই পরিবেশন করবে, যেহেতু একটি বন্ধ করে ভাগ করে নেওয়া ভেরিয়েবলে করা পরিবর্তনগুলি অবশ্যই অন্যটিকে দেখা উচিত। ভাগ করে নেওয়া এড়িয়ে চলার জন্য প্রতিটি বন্ধের নিজস্ব বস্তু যা নিজের ভাগ করা ভেরিয়েবলগুলি ধারণ করে সেই সাথে একটি ভাগ করা অবজেক্টের রেফারেন্স যা ভাগ করে নেওয়া ভেরিয়েবলগুলি ধারণ করে। অসম্ভব নয়, তবে এটি বেশিরভাগ ভেরিয়েবল অ্যাক্সেসগুলিতে ডিসিফেরেন্সের একটি অতিরিক্ত স্তর যুক্ত করে সমস্ত কিছু ধীর করে ফেলত।
সুপারক্যাট

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;)
থমাস জাঙ্ক

@ থমাস জাঙ্ক আমি নিশ্চিত না যে আমি বেশ অনুসরণ করি। কিভাবে একটি "হবে -accidental অবসান" চেহারা? আমি makeadderউপরে আপনার উদাহরণটি দেখেছি , যা আমার চোখে দেখা যায় অনেকটা একই। আপনি একটি "ত্রিযুক্ত" ফাংশন ফিরিয়ে দেন যা দুজনের পরিবর্তে একক আর্গ গ্রহণ করে; একই উপায় ব্যবহার করে, আমি একটি ফাংশন তৈরি করি যা শূন্য আর্গুমেন্ট নেয়। আমি কেবল এটি ফিরিয়ে দিচ্ছি না তবে setTimeoutপরিবর্তে এটি পাস করব ।
ফ্ল্যাম্বিনো

»আমি কেবল এটি ফিরিয়ে দিই না« সম্ভবত, এটিই আমার পক্ষে তাত্পর্যপূর্ণ। আমি আমার "উদ্বেগ" পুরোপুরি প্রকাশ করতে পারি না;) প্রযুক্তিগত দিক থেকে আপনি 100% সঠিক। উল্লেখ messageমধ্যে fireঅবসান জেনারেট করে। এবং এটিতে যখন এটি বলা হয় setTimeoutসংরক্ষণ করা রাষ্ট্রটি ব্যবহার করে।
থমাস

1
@ থমাস জাঙ্ক আমি দেখতে পাচ্ছি কীভাবে এটি কিছুটা ভিন্ন গন্ধ পেতে পারে। যদিও আমি আপনার উদ্বেগটি ভাগ করে নিতে পারি না, তবে :) বা, যে কোনও হারে, আমি এটিকে "দুর্ঘটনাজনক" বলব না - এটি নিশ্চিতভাবেই আমি এটিকে কোড করেছিলাম;)
ফ্ল্যাম্বিনো

3

পিএইচপি বিভিন্ন ভাষায় একটি আসল উদাহরণ দেখাতে সহায়তা করতে ব্যবহার করা যেতে পারে।

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: এটি তথ্য বাছাই একটি ফাংশন। আপনাকে এটি কোনও ফাংশনে একটি পয়েন্টার দিতে হবে যা দুটি বস্তুর তুলনা করে। সুতরাং আপনি একটি ফাংশন লিখতে হবে। এই ফাংশনটির প্যারামিটারাইজ করা দরকার হতে পারে যার অর্থ আপনি এটি স্ট্যাটিক ভেরিয়েবল দিচ্ছেন। যার অর্থ এটি থ্রেড নিরাপদ নয়। আপনি ডিএস এ আছেন সুতরাং আপনি একটি বিকল্প লিখুন যা কোনও ফাংশন পয়েন্টারের পরিবর্তে একটি বন্ধ করে নেয়। প্যারামিটারাইজেশনের সমস্যাটি আপনি তাত্ক্ষণিকভাবে সমাধান করুন কারণ প্যারামিটারগুলি বন্ধের অংশ হয়ে যায়। আপনি আপনার কোডটি আরও পঠনযোগ্য করে তোলেন কারণ আপনি কীভাবে লেখেন যে কোডগুলি কীভাবে বাছাইয়ের ফাংশনটিকে কল করে তার সাথে সরাসরি কীভাবে তুলনা করা হয়।

এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে আপনি কিছু ক্রিয়া সম্পাদন করতে চান যার জন্য বয়লার প্লেট কোডের একটি ভাল চুক্তি প্রয়োজন, সাথে সাথে একটি ছোট্ট কিন্তু প্রয়োজনীয় কোডের টুকরো যাতে অভিযোজিত হওয়া প্রয়োজন। আপনি একবার কোনও ফাংশন লিখে ক্লোজারের প্যারামিটারটি লিখে তার চারপাশের সমস্ত বয়লারপ্লেট কোডটি লিখে বয়লারপ্লেট কোডটি এড়াতে পারেন এবং তারপরে আপনি এই ফাংশনটি কল করতে পারেন এবং কোডটি বন্ধ হিসাবে মানিয়ে নিতে পাস করতে পারেন। কোড লেখার একটি খুব কমপ্যাক্ট এবং পঠনযোগ্য উপায়।

আপনার একটি ফাংশন রয়েছে যেখানে কিছু নন-তুচ্ছ কোডটি বিভিন্ন পরিস্থিতিতে বিভিন্ন পরিস্থিতিতে করা দরকার। এটি কোড নকল বা চুক্তিবদ্ধ কোড উভয়ই উত্পাদন করত যাতে অ-তুচ্ছ কোড কেবল একবার উপস্থিত হয়। তুচ্ছ: আপনি কোনও ভেরিয়েবলের জন্য একটি ক্লোজার নির্ধারণ করেন এবং এটি যেখানে প্রয়োজন সেখানে সর্বাধিক সুস্পষ্ট উপায়ে কল করুন।

মাল্টিথ্রেডিং: আইওএস / ম্যাকোস এক্সের "একটি ব্যাকগ্রাউন্ড থ্রেডে এই ক্লোজারটি সম্পাদন করা", "... মূল থ্রেডে", "... মূল থ্রেডে, এখন থেকে 10 সেকেন্ডের মতো কাজগুলি করার জন্য ফাংশন রয়েছে। এটি মাল্টিথ্রেডিংকে তুচ্ছ করে তোলে ।

অ্যাসিঙ্ক্রোনাস কল: ওপি এটি দেখেছিল। ইন্টারনেটে অ্যাক্সেস করে এমন কোনও কল বা সময় লাগতে পারে এমন অন্য কোনও কিছু (যেমন জিপিএস সমন্বয়গুলি পড়ার মতো) এমন একটি জিনিস যা আপনি ফলাফলটির জন্য অপেক্ষা করতে পারবেন না। সুতরাং আপনার ফাংশন রয়েছে যা ব্যাকগ্রাউন্ডে জিনিসগুলি করে এবং তারপরে শেষ হয়ে গেলে তাদের কী করতে হবে তা জানানোর জন্য আপনি একটি ক্লোজার পাস করেন।

এটি একটি ছোট শুরু। কমপ্যাক্ট, পঠনযোগ্য, নির্ভরযোগ্য এবং দক্ষ কোড তৈরির ক্ষেত্রে ক্লোজারগুলি বিপ্লবী এমন পাঁচটি পরিস্থিতি।


-4

ক্লোজার হ'ল একটি পদ্ধতি যেখানে এটি ব্যবহার করা হবে সেগুলি লেখার একটি সংক্ষিপ্ত উপায়। এটি আপনাকে আলাদা পদ্ধতি ঘোষণা করার এবং লেখার প্রয়াস রক্ষা করে। পদ্ধতিটি কেবল একবার ব্যবহার করা হবে এবং পদ্ধতির সংজ্ঞা সংক্ষিপ্ত হলে এটি কার্যকর হয়। ফাংশনটির নাম, এর রিটার্ন টাইপ বা এর অ্যাক্সেস মডিফায়ার নির্দিষ্ট করার প্রয়োজন নেই বলে সুবিধাগুলি টাইপিং হ্রাস পেয়েছে। এছাড়াও, কোডটি পড়ার সময় আপনাকে পদ্ধতির সংজ্ঞাটির জন্য অন্য কোথাও তাকাতে হবে না।

উপরেরটি ড্যান আভিদার দ্বারা বোঝে ল্যাম্বদা এক্সপ্রেশনগুলির সংক্ষিপ্তসার।

এটি আমার জন্য ক্লোজারগুলির ব্যবহারকে স্পষ্ট করেছে কারণ এটি বিকল্পগুলি (ক্লোজার বনাম পদ্ধতি) এবং প্রতিটিটির সুবিধাগুলিকে পরিষ্কার করে।

নিম্নলিখিত কোডটি একবার এবং একবার সেটআপের সময় ব্যবহৃত হয়। ডিডলয়েডের অধীনে এটিকে জায়গায় লিখলে এটি অন্য কোথাও অনুসন্ধানের সমস্যা বাঁচায় এবং কোডের আকার ছোট করে।

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
দুর্ভাগ্যক্রমে, এটি ক্লোজার এবং ল্যাম্বডাসকে বিভ্রান্ত করে। ল্যাম্বডাস প্রায়শই ক্লোজার ব্যবহার করে, কারণ এগুলি সাধারণত সংজ্ঞায়িত করা হয় তবে অনেক বেশি কার্যকর) ক) খুব ক্ষুদ্র এবং খ) ভেরিয়েবলগুলি সহ কোনও প্রদত্ত পদ্ধতির প্রেক্ষাপটে এবং এর উপর নির্ভর করে। তবে, ল্যাম্বডা ধারণার সাথে প্রকৃত বন্ধনের কোনও সম্পর্ক নেই, যা মূলত প্রথম শ্রেণির ফাংশনটি স্থানে সংজ্ঞায়িত করার এবং পরবর্তী ব্যবহারের জন্য পাশ কাটাতে সক্ষম।
নাথন টগি

আপনি যখন এই উত্তরটি নিচে ভোট দিচ্ছেন, এইটি পড়ুন ... কখন আমার ভোট দেওয়া উচিত? যখনই আপনি কোনও গুরুতরভাবে opালু, কোনও প্রচেষ্টা-ব্যয় করা পোস্ট, বা স্পষ্ট এবং সম্ভবত বিপজ্জনকরূপে ভুল একটি উত্তর সম্মুখীন হন আপনার ডাউনভোটগুলি ব্যবহার করুন। আমার উত্তরটিতে ক্লোজার ব্যবহারের কয়েকটি কারণ অভাবিত হতে পারে তবে এটি তীব্রভাবে মোড়ক বা বিপজ্জনকভাবে ভুলও নয়। ফাংশনাল প্রোগ্রামিং এবং ল্যাম্বডে স্বরলিপি কেন্দ্রটিতে ক্লোজারগুলির অনেকগুলি কাগজপত্র এবং আলোচনা রয়েছে। আমার সমস্ত উত্তর বলছে যে কার্যকরী প্রোগ্রামিংয়ের এই ব্যাখ্যাটি আমাকে ক্লোজারগুলি বুঝতে সহায়তা করেছিল। যে এবং অবিরাম মান।
বেনড্রিক্স

1
উত্তর সম্ভবত বিপজ্জনক নয় , তবে এটি অবশ্যই "স্পষ্টভাবে […] ভুল"। এটি ধারণাগুলির জন্য ভুল পদ ব্যবহার করে যা অত্যন্ত পরিপূরক এবং এইভাবে প্রায়শই একসাথে ব্যবহৃত হয় - ঠিক যেখানে পার্থক্যের স্পষ্টতা প্রয়োজনীয়। যদি সমস্যা সমাধান না করা হয় তবে এটি পড়ার জন্য প্রোগ্রামারদের ডিজাইনের সমস্যা হতে পারে। (এবং যেহেতু, আমি যতদূর বলতে পারি, কোড উদাহরণটিতে কেবল কোনও ক্লোজার নেই, কেবল একটি ল্যাম্বডা ফাংশন রয়েছে, এটি
বন্ধকরণ

নাথান, সেই কোড উদাহরণটি সুইফটে একটি বন্ধ। আপনি যদি আমাকে সন্দেহ করেন তবে আপনি অন্য কাউকে জিজ্ঞাসা করতে পারেন। সুতরাং, যদি এটি বন্ধ হয়ে যায়, আপনি কি ভোট দিয়ে যাবেন?
বেনড্রিক্স

1
অ্যাপল তাদের ডকুমেন্টেশনগুলিতে বন্ধ করে দিয়ে তারা যা বোঝায় তা মোটামুটি স্পষ্টভাবে বর্ণনা করে । "ক্লোজারগুলি ক্রিয়াকলাপের স্ব-অন্তর্ভুক্ত ব্লক যা আপনার কোডের চারপাশে পাস এবং ব্যবহার করা যেতে পারে Sw সুইফটে বন্ধগুলি সি এবং অবজেক্টিভ-সি এর ব্লক এবং অন্যান্য প্রোগ্রামিং ভাষায় ল্যাম্বডাসের সমান" " আপনি যখন বাস্তবায়ন এবং পরিভাষাটি পাবেন তখন বিভ্রান্তিকর হতে পারে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.