আমি সম্প্রতি প্রোগ্রামিং ভাষার একটি অনলাইন কোর্সে অংশ নিয়েছি যেখানে অন্যান্য ধারণাগুলির মধ্যে ক্লোজার উপস্থাপন করা হয়েছিল। আমি আমার প্রশ্ন জিজ্ঞাসার আগে কিছু প্রসঙ্গ দেওয়ার জন্য এই কোর্স দ্বারা অনুপ্রাণিত দুটি উদাহরণ লিখেছি।
প্রথম উদাহরণটি একটি এসএমএল ফাংশন যা 1 থেকে x পর্যন্ত সংখ্যার একটি তালিকা তৈরি করে, যেখানে এক্স ফাংশনের পরামিতি:
fun countup_from1 (x: int) =
let
fun count (from: int) =
if from = x
then from :: []
else from :: count (from + 1)
in
count 1
end
এসএমএল REPL এ:
val countup_from1 = fn : int -> int list
- countup_from1 5;
val it = [1,2,3,4,5] : int list
countup_from1
ফাংশন সাহায্যকারী অবসান ব্যবহার count
করে যেমনটি এবং পরিবর্তনশীল ব্যবহারসমূহ x
তার প্রসঙ্গ থেকে।
দ্বিতীয় উদাহরণে, আমি যখন কোনও ফাংশনটি আহ্বান করি, তখন আমি একটি ফাংশন create_multiplier t
ফিরে পাই (আসলে, একটি সমাপ্তি) যা তার যুক্তিকে টি দিয়ে বহুগুণ করে:
fun create_multiplier t = fn x => x * t
এসএমএল REPL এ:
- fun create_multiplier t = fn x => x * t;
val create_multiplier = fn : int -> int -> int
- val m = create_multiplier 10;
val m = fn : int -> int
- m 4;
val it = 40 : int
- m 2;
val it = 20 : int
সুতরাং ভেরিয়েবলটি m
ফাংশন কল দ্বারা ফিরে আসা বন্ধের সাথে আবদ্ধ এবং এখন আমি ইচ্ছামত এটি ব্যবহার করতে পারি।
এখন, ক্লোজারটির পুরো জীবনকাল ধরে সঠিকভাবে কাজ করার জন্য, আমাদের ক্যাপচারড ভেরিয়েবলের জীবনকাল বাড়ানো দরকার t
(উদাহরণস্বরূপ এটি একটি পূর্ণসংখ্যা তবে এটি কোনও ধরণের মান হতে পারে)। যতদূর আমি জানি, এসএমএলে এটি আবর্জনা সংগ্রহের মাধ্যমে সম্ভব হয়েছে: বন্ধটি হ'ল বন্দরের মানটির একটি রেফারেন্স রাখে যা পরে আবর্জনা সংগ্রহকারী দ্বারা বন্ধ হয়ে যাওয়ার পরে নিষ্পত্তি করা হয়।
আমার প্রশ্ন: সাধারণভাবে, আবর্জনা সংগ্রহ কি ক্লোজারগুলি নিরাপদ (তাদের পুরো জীবনকালে কলযোগ্য) তা নিশ্চিত করার একমাত্র সম্ভাব্য প্রক্রিয়া?
বা অন্যান্য এমন কী কী ব্যবস্থা আছে যা আবর্জনা সংগ্রহ না করে বন্ধের বৈধতা নিশ্চিত করতে পারে: বন্দী মূল্যবোধগুলি অনুলিপি করুন এবং এটি বন্ধের মধ্যে সংরক্ষণ করুন? বন্ধের জীবনকালকে নিজেই সীমাবদ্ধ রাখুন যাতে এর ক্যাপচারড ভেরিয়েবলগুলি শেষ হয়ে যাওয়ার পরে এটি আর চাওয়া যায় না?
সর্বাধিক জনপ্রিয় পদ্ধতিগুলি কী কী?
সম্পাদনা
আমি মনে করি না যে বন্দোবস্ত করা ভেরিয়েবল (গুলি) বন্ধ করে অনুলিপি করে উপরের উদাহরণটি ব্যাখ্যা / প্রয়োগ করা যেতে পারে। সাধারণভাবে, ক্যাপচারেড ভেরিয়েবলগুলি যে কোনও ধরণের হতে পারে, উদাহরণস্বরূপ এগুলি খুব বড় (অপরিবর্তনীয়) তালিকার সাথে আবদ্ধ হতে পারে। সুতরাং, বাস্তবায়নের ক্ষেত্রে এই মানগুলি অনুলিপি করা খুব অকার্যকর হবে।
সম্পূর্ণতার স্বার্থে, এখানে উল্লেখ (এবং পার্শ্ব প্রতিক্রিয়া) ব্যবহার করে অন্য একটি উদাহরণ দেওয়া হয়েছে:
(* Returns a closure containing a counter that is initialized
to 0 and is incremented by 1 each time the closure is invoked. *)
fun create_counter () =
let
(* Create a reference to an integer: allocate the integer
and let the variable c point to it. *)
val c = ref 0
in
fn () => (c := !c + 1; !c)
end
(* Create a closure that contains c and increments the value
referenced by it it each time it is called. *)
val m = create_counter ();
এসএমএল REPL এ:
val create_counter = fn : unit -> unit -> int
val m = fn : unit -> int
- m ();
val it = 1 : int
- m ();
val it = 2 : int
- m ();
val it = 3 : int
সুতরাং, ভেরিয়েবলগুলি রেফারেন্সের মাধ্যমেও ক্যাপচার করা যায় এবং তাদের ( create_counter ()
) সম্পন্ন হওয়ার পরে যে ফাংশন কল তৈরি হয়েছিল তার পরেও বেঁচে থাকবে ।