বন্ধ কী?


155

প্রতিবার এবং পরে আমি "ক্লোজার" উল্লেখ করা দেখছি, এবং আমি এটি দেখার চেষ্টা করেছি কিন্তু উইকি এমন একটি ব্যাখ্যা দেয় না যা আমি বুঝতে পেরেছি। এখানে কেউ আমাকে সাহায্য করতে পারে?


আপনি যদি জাভা / সি # জেনে থাকেন তবে আশা করি এই লিঙ্কটি সাহায্য করবে- http://www.developerfusion.com/article/8251/the-beauty-of-closures/
গুলশান

1
বন্ধগুলি বোঝা শক্ত। আপনার উইকিপিডিয়া নিবন্ধের প্রথম বাক্যে সমস্ত লিঙ্কটি ক্লিক করার চেষ্টা করা উচিত এবং সেই নিবন্ধগুলি প্রথমে বোঝার চেষ্টা করা উচিত।
জাচ


3
যদিও ক্লোজার এবং ক্লাসের মধ্যে মৌলিক পার্থক্য কি? ঠিক আছে, কেবল একটি জনসাধারণের পদ্ধতি সহ একটি শ্রেণি।
বিজিকলপ

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

উত্তর:


141

(অস্বীকৃতি: এটি একটি প্রাথমিক ব্যাখ্যা; সংজ্ঞা যতদূর যায় আমি কিছুটা সরল করছি)

ক্লোজারটি ভাবার সর্বাধিক সহজ উপায় হ'ল একটি ফাংশন যা একটি ভেরিয়েবল হিসাবে সংরক্ষণ করা যেতে পারে ("প্রথম শ্রেণির ফাংশন" হিসাবে পরিচিত), এতে অন্যান্য ভেরিয়েবল স্থানীয়ভাবে এটি তৈরির সুযোগে অ্যাক্সেস করার বিশেষ ক্ষমতা রাখে।

উদাহরণ (জাভাস্ক্রিপ্ট):

var setKeyPress = function(callback) {
    document.onkeypress = callback;
};

var initialize = function() {
    var black = false;

    document.onclick = function() {
        black = !black;
        document.body.style.backgroundColor = black ? "#000000" : "transparent";
    }

    var displayValOfBlack = function() {
        alert(black);
    }

    setKeyPress(displayValOfBlack);
};

initialize();

ক্রিয়াকলাপ 1 নিযুক্ত document.onclickএবং displayValOfBlackবন্ধ হয়। আপনি দেখতে পাচ্ছেন যে তারা উভয়ই বুলিয়ান ভেরিয়েবলটি উল্লেখ করে blackতবে সেই ভেরিয়েবলটি ফাংশনের বাইরে নির্ধারিত হয়। কারণ blackহল সুযোগ যেখানে ফাংশন সংজ্ঞায়িত করা হয় স্থানীয় , এই পরিবর্তনশীল পয়েন্টার সংরক্ষিত হয়।

আপনি যদি এইচটিএমএল পৃষ্ঠায় রাখেন:

  1. কালোতে পরিবর্তন করতে ক্লিক করুন
  2. "সত্য" দেখতে হিট করুন [প্রবেশ করুন]
  3. আবার ক্লিক করুন, সাদা থেকে ফিরে পরিবর্তন করুন
  4. "মিথ্যা" দেখতে [প্রবেশ করুন] টিপুন

এটি দেখায় যে উভয়েরই অ্যাক্সেস একইরকম black এবং কোনও মোড়কযুক্ত বস্তু ছাড়াই রাষ্ট্র সঞ্চয় করতে ব্যবহার করা যেতে পারে ।

কলটি setKeyPressহ'ল যে কোনও ফাংশন ঠিক যেমন কোনও ভেরিয়েবলের মতো কীভাবে পাশ করা যায় তা প্রদর্শন করা। সুযোগ অবসান সংরক্ষিত এখনও এক যেখানে ম ফাংশন পূর্বনির্ধারণ হয়।

বন্ধগুলি ইভেন্ট হ্যান্ডলার হিসাবে সাধারণত ব্যবহৃত হয়, বিশেষত জাভাস্ক্রিপ্ট এবং অ্যাকশনস্ক্রিপ্টে। ক্লোজারগুলির ভাল ব্যবহার আপনাকে অবজেক্ট র‌্যাপার তৈরি না করে ইভেন্ট হ্যান্ডলারগুলিতে সুস্পষ্টভাবে বেঁধে রাখতে সহায়তা করবে। তবে, অসাবধান ব্যবহারের ফলে মেমোরি ফাঁস হতে পারে (যেমন যখন কোনও অব্যবহৃত তবে সংরক্ষিত ইভেন্ট হ্যান্ডলার কেবল মেমরির বৃহত অবজেক্টগুলিতে বিশেষত ডিওএম অবজেক্টগুলিকে ধরে রাখতে পারে, আবর্জনা সংগ্রহ রোধ করে)।


1: আসলে, জাভাস্ক্রিপ্টের সমস্ত ফাংশন ক্লোজার।


3
আমি যখন আপনার উত্তরটি পড়ছিলাম তখন মনে হচ্ছিল আমার মনে একটি হালকা বোল চালু। অনেক প্রশংসিত! :)
জে

1
যেহেতু blackকোনও ফাংশনের অভ্যন্তরে ঘোষণা করা হয়েছে, তাই স্ট্যাকটি আনইন্ডিংস হিসাবে ধ্বংস হবে না ...?
গ্যাবলিন

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

2
@ গ্যাবলিন, এটি একটি ভাল প্রশ্ন। আমি মনে করি না তারা & mdash করতে পারে না ; তবে জেএস যা ব্যবহার করে তা কেবলমাত্র আবর্জনা সংগ্রহের জন্যই এনেছি এবং আপনি যখন বলেছিলেন যে "যেহেতু blackকোনও ফাংশনের অভ্যন্তরে ঘোষণা করা হয়েছে, তাই এটি ধ্বংস হবে না " said এও মনে রাখবেন যে আপনি যদি কোনও ফাংশনে কোনও অবজেক্ট ঘোষণা করেন এবং তারপরে এটি অন্য কোনও স্থানে বাস করে এমন একটি ভেরিয়েবলের কাছে অর্পণ করেন তবে সেই বস্তুটি সংরক্ষিত রয়েছে কারণ এর সাথে অন্যান্য উল্লেখ রয়েছে।
নিকোল

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

68

একটি ক্লোজারটি মূলত কোনও অবজেক্টের দিকে তাকানোর আলাদা উপায়। একটি অবজেক্ট এমন ডেটা যা এর সাথে আবদ্ধ এক বা একাধিক ফাংশন। ক্লোজার হ'ল এমন একটি ফাংশন যা এর সাথে আবদ্ধ এক বা একাধিক ভেরিয়েবল। কমপক্ষে বাস্তবায়ন স্তরে দুটি মূলত অভিন্ন। আসল পার্থক্য তারা কোথা থেকে এসেছে in

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

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


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

3
খুব ভাল উত্তর। এটি আসলে বন্ধের অন্তর্দৃষ্টি ব্যাখ্যা করে।
রোবএলাক্স

1
@ ম্যাসন হুইলার: ক্লোজার ডেটা কোথায় পাওয়া যায়? একটি ফাংশন মত স্ট্যাক? নাকি কোনও বস্তুর মতো গাদা?
রোবওএলেক্স

1
@ রবোআলাক্স: স্তূপে, কারণ এটি এমন কোনও বস্তু যা কোনও ফাংশনের মতো দেখাচ্ছে
ম্যাসন হুইলারের

1
@ রবোআলেক্স: যেখানে কোনও বন্ধ এবং এর ক্যাপচারিত ডেটা সংরক্ষণ করা হয়েছে তা প্রয়োগের উপর নির্ভর করে। সি ++ এ এটি হিপ বা স্ট্যাকের মধ্যে সংরক্ষণ করা যেতে পারে।
জর্জিও

29

মেয়াদ অবসান আসলে কোড (ব্লক, ফাংশন) এক টুকরা বিনামূল্যে ভেরিয়েবল যে থাকতে পারে যে থেকে আসে বন্ধ (অর্থাত একটি মান আবদ্ধ) পরিবেশ যা কোডের ব্লক সংজ্ঞায়িত করা হয় দ্বারা।

উদাহরণস্বরূপ স্কেলা ফাংশন সংজ্ঞাটি ধরুন:

def addConstant(v: Int): Int = v + k

ফাংশন বডিটিতে দুটি নাম (ভেরিয়েবল) vএবং kদুটি পূর্ণসংখ্যার মান নির্দেশ করে। নামটি vআবদ্ধ কারণ এটি ফাংশনটির আর্গুমেন্ট হিসাবে ঘোষিত হয়েছে addConstant(ফাংশন ঘোষণার দিকে তাকিয়ে আমরা জানি যে vফাংশনটি চালু করার সময় একটি মান নির্ধারিত হবে)। নামটি kনিখরচায় ফাংশন করে addConstantকারণ ফাংশনে কোনও মানটি k(এবং কীভাবে) আবদ্ধ সে সম্পর্কে কোনও ধারণা নেই ।

যেমন একটি কল মূল্যায়ন করার জন্য:

val n = addConstant(10)

আমাদের kএকটি মান নির্ধারণ করতে হবে, যা কেবল তখনই ঘটতে পারে যখন নামটি kপ্রসঙ্গে addConstantসংজ্ঞায়িত করা হয়। উদাহরণ স্বরূপ:

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  def addConstant(v: Int): Int = v + k

  values.map(addConstant)
}

এখন আমরা addConstantএকটি প্রসঙ্গে যেখানে kসংজ্ঞায়িত করা addConstantহয়েছে তা সংজ্ঞায়িত করেছি, এটি একটি বন্ধ হয়ে গেছে কারণ এর সমস্ত ফ্রি ভেরিয়েবল এখন বন্ধ হয়ে গেছে (একটি মানের সাথে আবদ্ধ): addConstantএটি অনুরোধ করা যেতে পারে এবং এটি কোনও ফাংশন হিসাবে ঘুরতে পারে। ক্লোজারটি সংজ্ঞায়িতk হওয়ার পরে মুক্ত ভেরিয়েবলটি একটি মানের সাথে আবদ্ধ হয় তা নোট করুন , যখন ক্লোজারটি আহ্বান করা হলে আর্গুমেন্ট ভেরিয়েবলটি আবদ্ধ হয়v

সুতরাং একটি ক্লোজারটি মূলত একটি ফাংশন বা কোড ব্লক যা প্রসঙ্গ দ্বারা আবদ্ধ হওয়ার পরে এটির মুক্ত ভেরিয়েবলের মাধ্যমে অ-স্থানীয় মানগুলিতে অ্যাক্সেস করতে পারে।

অনেক ভাষায়, আপনি যদি একবার বন্ধ ব্যবহার করেন তবে একবার এটি বেনামে রাখতে পারেন , যেমন

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  values.map(v => v + k)
}

নোট করুন যে কোনও ফ্রি ভেরিয়েবলগুলি নেই এমন একটি ফাংশন হ'ল বন্ধের একটি বিশেষ কেস (বিনামূল্যে ভেরিয়েবলের খালি সেট সহ)। আনুষাঙ্গিকভাবে, একটি বেনামে ফাংশন একটি বেনামে বন্ধের একটি বিশেষ ক্ষেত্রে , অর্থাত্ একটি বেনাম ফাংশন কোনও বেনামে কোনও মুক্ত ভেরিয়েবল নেই closure


যুক্তিতে বন্ধ এবং খোলা সূত্রগুলি সহ এই জিবগুলি ভাল। আপনার উত্তরের জন্য ধন্যবাদ.
রেইনডক্টর

@ রাইনডোক্টর: ফ্রি ভেরিয়েবলগুলি লজিক সূত্রে এবং ল্যাম্বডা ক্যালকুলাস এক্সপ্রেশনগুলিতে একইভাবে সংজ্ঞায়িত হয়: ল্যাম্বডা এক্সপ্রেশনটিতে ল্যাম্বডা যুক্তি সূত্রে আর্ট ফ্রি / বাউন্ড ভেরিয়েবলের পরিমাণের মতো কাজ করে।
জর্জিও

9

জাভাস্ক্রিপ্টের একটি সহজ ব্যাখ্যা:

var closure_example = function() {
    var closure = 0;
    // after first iteration the value will not be erased from the memory
    // because it is bound with the returned alertValue function.
    return {
        alertValue : function() {
            closure++;
            alert(closure);
        }
    };
};
closure_example();

alert(closure)এর পূর্বে নির্মিত মান ব্যবহার করবে closure। ফিরে আসা alertValueফাংশনটির নামস্থানটি সেই স্থানের সাথে যুক্ত হবে যেখানে closureভেরিয়েবলটি থাকে। আপনি যখন পুরো ফাংশনটি মুছবেন তখন closureভেরিয়েবলের মান মুছে যাবে তবে ততক্ষণ পর্যন্ত alertValueফাংশনটি সর্বদা ভেরিয়েবলের মান পড়তে / লিখতে সক্ষম হবে closure

আপনি যদি এই কোডটি চালনা করেন তবে প্রথম পুনরাবৃত্তিটি closureভেরিয়েবলের 0 মান প্রদান করবে এবং এতে ফাংশনটি পুনরায় লিখবে:

var closure_example = function(){
    alertValue : function(){
        closure++;
        alert(closure);
    }       
}

এবং ফাংশনটি সম্পাদন করতে alertValueস্থানীয় ভেরিয়েবলের প্রয়োজন হওয়ায় closureএটি পূর্বে নির্ধারিত স্থানীয় ভেরিয়েবলের মানের সাথে আবদ্ধ হয় closure

এবং এখন আপনি যখনই closure_exampleফাংশনটি কল করবেন তখন এটি closureভেরিয়েবলের বর্ধিত মানটি লিখবে কারণ alert(closure)আবদ্ধ।

closure_example.alertValue()//alerts value 1 
closure_example.alertValue()//alerts value 2 
closure_example.alertValue()//alerts value 3
//etc. 

ধন্যবাদ, আমি কোডটি পরীক্ষা করিনি =) সবকিছু এখন ঠিক আছে বলে মনে হচ্ছে।
মুহা

5

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

দুর্ভাগ্যক্রমে, অপরিচিত থাকার কারণে এটি ব্যাখ্যা করা কিছুটা কঠিন It's

অতীতে সফলভাবে ব্যবহৃত একটি উপমাটি ছিল "ধারণা করুন আমাদের কাছে এমন কিছু আছে যা আমরা 'বই' বলি, রুম-ক্লোজারে, 'বই' হ'ল সেই অনুলিপিটি সেখানে, কোণে, টিএওসিপি-র, কিন্তু টেবিল-ক্লোজারে রয়েছে এটি কোনও ড্রেসডেন ফাইলের বইয়ের অনুলিপি So সুতরাং আপনি কী বন্ধ হয়ে আছেন তার উপর নির্ভর করে কোডটি 'আমাকে বইটি দাও' এর ফলে বিভিন্ন জিনিস ঘটবে results


আপনি এটি ভুলে গেছেন: en.wikedia.org/wiki/Closure_( কম্পিউটার_প্রগ্রামিং) আপনার উত্তরে।
এস। লট

3
না, আমি দৃious়তার সাথে সেই পৃষ্ঠাটি বন্ধ না করা বেছে নিয়েছি।
ভ্যাটাইন

"স্টেট এবং ফাংশন।": staticস্থানীয় ভেরিয়েবল সহ সি ফাংশনকে কি বন্ধ হিসাবে বিবেচনা করা যেতে পারে? হাস্কেল বন্ধের সাথে কি রাষ্ট্র জড়িত?
জর্জিও

2
হাস্কেলের @ জর্জিও ক্লোজারগুলি (আমি বিশ্বাস করি) তাদের যে সংজ্ঞা দেওয়া হয়েছে সেগুলি যুক্ত করার জন্য যুক্তিগুলি বন্ধ করে দেয় (তাই আমি বিশ্বাস করি) "হ্যাঁ" বলব (যদিও আমি হাস্কেলের সাথে সবচেয়ে অপরিচিত)। একটি স্ট্যাটিক ভেরিয়েবল সহ এসি ফাংশনটি সর্বোপরি খুব সীমাবদ্ধ বন্ধ (আপনি সত্যই staticস্থানীয় ভেরিয়েবল সহ একক ফাংশন থেকে একাধিক ক্লোজার তৈরি করতে সক্ষম হতে চান ), আপনার ঠিক একটি রয়েছে।
ভ্যাটাইন

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

5

'রাষ্ট্র' ধারণাটি সংজ্ঞায়িত না করে বন্ধ কী কী তা নির্ধারণ করা শক্ত।

মূলত, সম্পূর্ণ লেজিকাল স্কোপিংয়ের ভাষায় যা ফাংশনটিকে প্রথম শ্রেণির মান হিসাবে বিবেচনা করে, বিশেষ কিছু ঘটে। আমি যদি এমন কিছু করি:

function foo(x)
return x
end

x = foo

পরিবর্তনশীলটি xকেবল রেফারেন্সই function foo()নয় তবে এটি উল্লেখ করে যে রাজ্যটি fooশেষ সময় ফিরে এসেছিল। আসল যাদুটি তখন ঘটে যখন fooঅন্যান্য কার্যগুলি তার ক্ষেত্রের মধ্যে আরও সংজ্ঞায়িত করা হয়; এটি নিজস্ব মিনি-পরিবেশের মতো (ঠিক 'সাধারণভাবে' আমরা একটি বিশ্ব পরিবেশে ফাংশনগুলি সংজ্ঞায়িত করি)।

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

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

লুয়ার ক্লোজার সাপোর্টের এখানে কিছু পরীক্ষা করা হচ্ছে।

--Closure testing
--By Trae Barlow
--

function myclosure()
    print(pvalue)--nil
    local pvalue = pvalue or 10
    return function()
        pvalue = pvalue + 10 --20, 31, 42, 53(53 never printed)
        print(pvalue)
        pvalue = pvalue + 1 --21, 32, 43(pvalue state saved through multiple calls)
        return pvalue
    end
end

x = myclosure() --x now references anonymous function inside myclosure()

x()--nil, 20
x() --21, 31
x() --32, 42
    --43, 53 -- if we iterated x() again

ফলাফল:

nil
20
31
42

এটি জটিল হয়ে উঠতে পারে এবং এটি সম্ভবত ভাষা থেকে আলাদা হয়ে যায় তবে লুয়ায় মনে হয় যে যখনই কোনও ফাংশন সম্পাদন করা হয় তখন তার অবস্থা পুনরায় সেট করা হয়। আমি এটি বলছি কারণ উপরের কোড থেকে ফলাফলগুলি পৃথক হবে যদি আমরা myclosureসরাসরি ফাংশন / রাজ্যে অ্যাক্সেস করে থাকি (বেনামে ফাংশনটি পরিবর্তনের পরিবর্তে) এটি pvalueপুনরায় সেট করা হয় 10; তবে যদি আমরা এক্স (বেনামে ফাংশন) এর মাধ্যমে মাইক্লোজারের রাজ্যে অ্যাক্সেস করতে পারি তবে আপনি দেখতে পাচ্ছেন যে pvalueএটি স্মরণে কোথাও বেঁচে আছে well আমার সন্দেহ হয় এর আরও কিছু আছে, সম্ভবত কেউ বাস্তবায়নের প্রকৃতি আরও ভালভাবে ব্যাখ্যা করতে পারে।

পিএস: আমি সি ++ 11 (আগের সংস্করণগুলির তুলনায় অন্য) কে চিনি না, সুতরাং লক্ষ করুন যে এটি সি ++ 11 এবং লুয়ার ক্লোজারগুলির মধ্যে তুলনা নয়। এছাড়াও, লুয়া থেকে সি ++ পর্যন্ত আঁকা সমস্ত 'লাইনগুলি স্থির ভেরিয়েবল এবং ক্লোজারগুলি 100% একই নয় বলে মিল; এমনকি যদি তারা কখনও কখনও একই সমস্যা সমাধানে ব্যবহৃত হয়।

আমি যে জিনিসটির বিষয়ে নিশ্চিত নই সেগুলি হ'ল উপরের কোড উদাহরণে বেনাম ফাংশন বা উচ্চতর ক্রম ফাংশনটি বন্ধ হিসাবে বিবেচনা করা হচ্ছে কিনা?


4

একটি বন্ধন একটি ফাংশন যা সম্পর্কিত রাষ্ট্র সম্পর্কিত:

পার্লে আপনি এর মতো ক্লোজার তৈরি করেন:

#!/usr/bin/perl

# This function creates a closure.
sub getHelloPrint
{
    # Bind state for the function we are returning.
    my ($first) = @_;a

    # The function returned will have access to the variable $first
    return sub { my ($second) = @_; print  "$first $second\n"; };
}

my $hw = getHelloPrint("Hello");
my $gw = getHelloPrint("Goodby");

&$hw("World"); // Print Hello World
&$gw("World"); // PRint Goodby World

যদি আমরা সি ++ সরবরাহিত নতুন কার্যকারিতাটি দেখি।
এটি আপনাকে অবজেক্টের সাথে বর্তমান অবস্থা বাঁধতেও সহায়তা করে:

#include <string>
#include <iostream>
#include <functional>


std::function<void(std::string const&)> getLambda(std::string const& first)
{
    // Here we bind `first` to the function
    // The second parameter will be passed when we call the function
    return [first](std::string const& second) -> void
    {   std::cout << first << " " << second << "\n";
    };
}

int main(int argc, char* argv[])
{
    auto hw = getLambda("Hello");
    auto gw = getLambda("GoodBye");

    hw("World");
    gw("World");
}

2

আসুন একটি সাধারণ ক্রিয়া বিবেচনা করুন:

function f1(x) {
    // ... something
}

এই ফাংশনটিকে শীর্ষ স্তরের ফাংশন বলা হয় কারণ এটি অন্য কোনও ফাংশনের মধ্যে বাসা বাঁধে না। প্রতিটি জাভাস্ক্রিপ্ট ফাংশন নিজের সাথে "স্কোপ চেইন" নামে পরিচিত বস্তুর একটি তালিকা সংযুক্ত করে । এই স্কোপ চেইনটি বস্তুর একটি আদেশযুক্ত তালিকা। এই প্রতিটি বস্তু কিছু পরিবর্তনশীল সংজ্ঞায়িত করে।

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

যখন এই ফাংশনটি চালু করা হয়, জাভাস্ক্রিপ্ট একটি "অ্যাক্টিভেশন অবজেক্ট" নামক কিছু তৈরি করে এবং স্কোপ চেইনের শীর্ষে রাখে। এই অবজেক্টে সমস্ত স্থানীয় ভেরিয়েবল রয়েছে (উদাহরণস্বরূপ xএখানে)। সুতরাং এখন স্কোপ চেইনে আমাদের দুটি অবজেক্ট রয়েছে: প্রথমটি হল অ্যাক্টিভেশন অবজেক্ট এবং এর নীচে বিশ্বব্যাপী অবজেক্ট।

খুব সাবধানে লক্ষ করুন যে দুটি বিষয়গুলি বিভিন্ন সময়ে স্কোপ চেইনে রাখা হয়। ফাংশনটি সংজ্ঞায়িত হয়ে গেলে (যেমন, জাভাস্ক্রিপ্ট যখন ফাংশনটিকে বিশ্লেষণ করে ফাংশনটি তৈরি করে) গ্লোবাল অবজেক্ট স্থাপন করা হয় এবং ফাংশনটি চালিত হওয়ার সময় অ্যাক্টিভেশন অবজেক্ট প্রবেশ করে।

সুতরাং, আমরা এখন এটি জানি:

  • প্রতিটি ফাংশন এর সাথে যুক্ত একটি স্কোপ চেইন থাকে
  • যখন ফাংশনটি সংজ্ঞায়িত করা হয় (যখন ফাংশন অবজেক্ট তৈরি করা হয়), জাভাস্ক্রিপ্ট সেই ফাংশনটির সাথে স্কোপ চেইন সংরক্ষণ করে
  • শীর্ষ স্তরের ফাংশনগুলির জন্য, স্কোপ চেইনে কেবলমাত্র ফাংশন সংজ্ঞা সময়ে গ্লোবাল অবজেক্ট থাকে এবং অনুরোধের সময় শীর্ষে একটি অতিরিক্ত অ্যাক্টিভেশন অবজেক্ট যুক্ত করে

পরিস্থিতি আকর্ষণীয় হয়ে ওঠে যখন আমরা নেস্টেড ফাংশনগুলি নিয়ে কাজ করি। সুতরাং, আসুন এটি তৈরি করুন:

function f1(x) {

    function f2(y) {
        // ... something
    }

}

f1সংজ্ঞায়িত হয়ে গেলে আমরা কেবলমাত্র বৈশ্বিক অবজেক্টযুক্ত এর জন্য একটি স্কোপ চেইন পাই।

এখন যখন f1ডাকা হয়, স্কোপ চেইনটি f1অ্যাক্টিভেশন অবজেক্টটি পায়। এই অ্যাক্টিভেশন অবজেক্টে ভেরিয়েবল xএবং ভেরিয়েবল রয়েছে f2যা একটি ফাংশন। এবং, নোট যে f2সংজ্ঞায়িত হচ্ছে। সুতরাং, এই সময়ে, জাভাস্ক্রিপ্ট এছাড়াও জন্য একটি নতুন স্কোপ চেইন সংরক্ষণ করে f2এই অভ্যন্তরীণ ফাংশনটির জন্য স্কোপ চেইন সংরক্ষণ করা বর্তমান স্কোপ চেইন কার্যকর। বর্তমান স্কোপ চেইন কার্যকর হয় f1s অত: পর f2'র সুযোগ চেইন হয় f1s' এর বর্তমান যার অ্যাক্টিভেশন বস্তুর মধ্যে রয়েছে - সুযোগ শৃঙ্খল f1ও বৈশ্বিক অবজেক্ট।

যখন f2ডাকা হয়, এটি তার নিজস্ব অ্যাক্টিভেশন অবজেক্টটি ধারণ করে y, এর স্কোপ চেইনে যুক্ত হয় যা ইতিমধ্যে অ্যাক্টিভেশন অবজেক্ট f1এবং গ্লোবাল অবজেক্ট ধারণ করে ।

যদি এর মধ্যে অন্য কোনও নেস্টেড ফাংশন সংজ্ঞায়িত করা হয় তবে f2এর স্কোপ চেইনে সংজ্ঞা সময়ে তিনটি অবজেক্ট (দুটি বহিরাগত ক্রিয়াকলাপগুলির 2 টি অ্যাক্টিভেশন অবজেক্ট এবং বৈশ্বিক বস্তু) থাকবে এবং অনুরোধের সময় 4 থাকবে।

সুতরাং, এখন আমরা বুঝতে পারি যে স্কোপ চেইন কীভাবে কাজ করে তবে আমরা এখনও বন্ধ হওয়ার বিষয়ে কথা বলিনি।

একটি ফাংশন অবজেক্ট এবং স্কোপ (ভেরিয়েবল বাইন্ডিংগুলির একটি সেট) এর সংমিশ্রণ যেখানে ফাংশনের ভেরিয়েবলগুলি সমাধান করা হয় তাকে কম্পিউটার বিজ্ঞান সাহিত্যের একটি ক্লোজার বলা হয় - জাভাস্ক্রিপ্ট ডেভিড ফ্লানাগনের চূড়ান্ত গাইড

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

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

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

আমাদের উপরের উদাহরণে, আমরা এ f2থেকে ফিরে f1আসি না , অতএব, যখন কোনও কল f1ফিরে আসে, তখন তার সক্রিয়করণ অবজেক্টটি তার স্কোপ চেইন এবং সংগ্রহ করা আবর্জনা থেকে সরানো হবে। তবে আমাদের যদি এরকম কিছু থাকে:

function f1(x) {

    function f2(y) {
        // ... something
    }

    return f2;
}

এখানে, ফিরে আসার f2জন্য একটি স্কোপ চেইন থাকবে যার সক্রিয়করণ অবজেক্ট f1থাকবে এবং তাই এটি আবর্জনা সংগ্রহ করা হবে না। এই মুহুর্তে, আমরা যদি কল করি তবে এটি বাইরে না থাকলেও f2এটির f1ভেরিয়েবল অ্যাক্সেস করতে সক্ষম হবে ।xf1

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

এমন অনেকগুলি শক্তিশালী প্রোগ্রামিং কৌশল রয়েছে যাতে প্রাইভেট ভেরিয়েবল, ইভেন্ট চালিত প্রোগ্রামিং, আংশিক প্রয়োগ ইত্যাদির মতো ক্লোজার জড়িত থাকে

এছাড়াও মনে রাখবেন যে এই সমস্তগুলি সেই সমস্ত ভাষার ক্ষেত্রে প্রযোজ্য যা ক্লোজার সমর্থন করে। উদাহরণস্বরূপ পিএইচপি (5.3+), পাইথন, রুবি ইত্যাদি


-1

একটি বন্ধ হ'ল একটি সংকলক অপ্টিমাইজেশন (ওরফে সিনট্যাকটিক চিনি?)। কিছু লোক এটিকে দরিদ্র মানুষের উদ্দেশ্য হিসাবেও উল্লেখ করেছেন।

এরিক লিপার্টের উত্তর দেখুন : (নীচে অংশ)

সংকলক এই জাতীয় কোড উত্পন্ন করবে:

private class Locals
{
  public int count;
  public void Anonymous()
  {
    this.count++;
  }
}

public Action Counter()
{
  Locals locals = new Locals();
  locals.count = 0;
  Action counter = new Action(locals.Anonymous);
  return counter;
}

ধারণা তৈরী কর?
এছাড়াও, আপনি তুলনা চেয়েছিলেন। ভিবি এবং জেএসক্রিপ্ট উভয়ই একই উপায়ে ক্লোজার তৈরি করে।


এই উত্তরটি একটি সিডব্লিউ কারণ আমি এরিকের দুর্দান্ত উত্তরের জন্য পয়েন্টগুলির প্রাপ্য নই। আপনি উপযুক্ত হিসাবে দেখুন এটি upvote। আছে HTH
goodguys_activate

3
-1: আপনার ব্যাখ্যাটি সি # তে খুব মূল। বন্ধ অনেক ভাষায় ব্যবহৃত হয় এবং এই ভাষাগুলিতে সিনট্যাকটিক চিনির চেয়ে অনেক বেশি এবং ফাংশন এবং রাজ্য উভয়কেই অন্তর্ভুক্ত করে।
মার্টিন ইয়র্ক

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