কেউ ব্যাখ্যা করতে পারে? আমি তাদের পিছনে মূল ধারণাগুলি বুঝতে পারছি তবে আমি প্রায়শই সেগুলি আন্তঃআযোগযোগ্যভাবে ব্যবহার করতে দেখি এবং আমি বিভ্রান্ত হয়ে পড়ি।
এবং এখন আমরা এখানে এসেছি, তারা কীভাবে একটি নিয়মিত ফাংশন থেকে আলাদা?
কেউ ব্যাখ্যা করতে পারে? আমি তাদের পিছনে মূল ধারণাগুলি বুঝতে পারছি তবে আমি প্রায়শই সেগুলি আন্তঃআযোগযোগ্যভাবে ব্যবহার করতে দেখি এবং আমি বিভ্রান্ত হয়ে পড়ি।
এবং এখন আমরা এখানে এসেছি, তারা কীভাবে একটি নিয়মিত ফাংশন থেকে আলাদা?
উত্তর:
একটি ল্যাম্বদা কেবল একটি বেনামে ফাংশন - কোনও ফাংশন যার নাম নেই defined স্কিমের মতো কিছু ভাষায় এগুলি নামযুক্ত ফাংশনের সমতুল্য। আসলে, ফাংশন সংজ্ঞাটি একটি ল্যাম্বডাকে একটি ভেরিয়েবলের অভ্যন্তরীণভাবে বাঁধাই হিসাবে পুনরায় লেখা হয়। পাইথনের মতো অন্যান্য ভাষায়ও তাদের মধ্যে কিছু (বরং অপ্রয়োজনীয়) পার্থক্য রয়েছে, তবে তারা অন্যভাবে একইভাবে আচরণ করে।
একজন অবসান কোনো ফাংশন যা ওভার বন্ধ পরিবেশ যেখানে এটি সংজ্ঞায়িত করা হয়। এর অর্থ এটি প্যারামিটার তালিকায় নয় ভেরিয়েবল অ্যাক্সেস করতে পারে। উদাহরণ:
def func(): return h
def anotherfunc(h):
return func()
এই সময় একটি ত্রুটি কারণ হবে, কারণ func
না ধরে ঘনিষ্ঠ পরিবেশে anotherfunc
- h
undefined করা হয়। func
শুধুমাত্র বিশ্বব্যাপী পরিবেশ বন্ধ করে দেয়। এটি কাজ করবে:
def anotherfunc(h):
def func(): return h
return func()
কারণ এখানে, func
সংজ্ঞায়িত হয়েছে anotherfunc
, এবং পাইথন ২.৩ এবং এর চেয়ে বড় (বা এটির মতো কিছু সংখ্যক) যখন তারা প্রায় বন্ধ হয়ে গেছে ঠিকঠাক (রূপান্তর এখনও কাজ করে না), এর অর্থ এই যে এটি পরিবেশের উপর দিয়ে বন্ধ হয়ে যায় anotherfunc
এবং এর ভিতরে ভেরিয়েবল অ্যাক্সেস করতে পারে এটা। পাইথন ৩.১++-তে, কীওয়ার্ডটি ব্যবহার করারnonlocal
সময় মিউটেশন খুব কার্যকর হয় ।
আরেকটি গুরুত্বপূর্ণ বিষয় - এটির আর মূল্যায়ন না করা হলেও এমনকি তার পরিবেশকে func
বন্ধ করতে থাকবে । এই কোডটিও কাজ করবে:anotherfunc
anotherfunc
def anotherfunc(h):
def func(): return h
return func
print anotherfunc(10)()
এটি 10 মুদ্রণ করবে।
এটি যেমন আপনি লক্ষ্য করেছেন, ল্যাম্বডা এর সাথে কোনও সম্পর্ক নেই - এগুলি দুটি পৃথক (যদিও সম্পর্কিত) ধারণা are
ল্যাম্বডাস এবং ক্লোজারগুলির চারপাশে প্রচুর বিভ্রান্তি রয়েছে, এমনকি এই স্ট্যাকওভারফ্লো প্রশ্নের এখানে উত্তরও রয়েছে। র্যান্ডম প্রোগ্রামারদের যারা নির্দিষ্ট প্রোগ্রামিং ভাষার বা অন্যান্য পুনের প্রোগ্রামারদের সঙ্গে অনুশীলন থেকে বন্ধ সম্পর্কে শিখেছি চাওয়ার পরিবর্তে, আপনি একটি যাত্রা নেওয়া উৎস (যেখানে এটি সমস্ত শুরু করেন)। যেহেতু lambdas এবং বন্ধ আসা থেকে ল্যামডা ক্যালকুলাস '30s আগে প্রথম ইলেকট্রনিক কম্পিউটার এমনকি অস্তিত্ব মধ্যে অ্যালোঞ্জো চার্চ ফিরে দ্বারা আবিষ্কৃত, এই উৎস আমি যে বিষয়ে কথা বলছি।
ল্যাম্বদা ক্যালকুলাস বিশ্বের সহজ প্রোগ্রামিং ভাষা। আপনি কেবল এতে কাজ করতে পারেন: ►
f x
। f
এবং x
এটির একমাত্র পরামিতি)λ
(ল্যাম্বদা), তারপরে প্রতীকী নাম (উদাঃ x
), তারপরে .
অভিব্যক্তির আগে একটি বিন্দুর সাহায্যে করা হয়। এটি তখন একটি প্যারামিটারের প্রত্যাশা করে ক্রিয়াটিকে ফাংশনে রূপান্তর করে । উদাহরণস্বরূপ: এক্সপ্রেশনটি নেয় এবং বলে যে এই অভিব্যক্তির প্রতীকটি একটি সীমাবদ্ধ পরিবর্তনশীল - এটি প্যারামিটার হিসাবে সরবরাহ করে এমন একটি মানের সাথে প্রতিস্থাপিত হতে পারে।
মনে রাখবেন যে এইভাবে সংজ্ঞায়িত ফাংশনটি বেনামেλx.x+2
x+2
x
(λx.x+2) 7
। তারপরে এক্সপ্রেশনটি (এই ক্ষেত্রে একটি আক্ষরিক মান) প্রয়োগ করা ল্যাম্বদা এর subexpression 7
হিসাবে প্রতিস্থাপন করা x
হয় x+2
, সুতরাং আপনি পাবেন 7+2
, যা পরে 9
সাধারণ পাটিগণিত নিয়ম দ্বারা হ্রাস ।সুতরাং আমরা একটি রহস্য সমাধান করেছি:
লাম্বদা হ'ল উপরের উদাহরণ থেকে অজ্ঞাতনামা ফাংশনλx.x+2
,।
function(x) { return x+2; }
এবং আপনি অবিলম্বে এটি এর মতো কিছু প্যারামিটারে এটি প্রয়োগ করতে পারেন:
(function(x) { return x+2; })(7)
অথবা আপনি এই বেনাম ফাংশন (ল্যাম্বদা) কিছু ভেরিয়েবলের মধ্যে সঞ্চয় করতে পারেন:
var f = function(x) { return x+2; }
যা কার্যকরভাবে এটিকে একটি নাম f
দেয়, আপনাকে এটি উল্লেখ করতে এবং পরে একাধিকবার কল করার অনুমতি দেয়, যেমন:
alert( f(7) + f(10) ); // should print 21 in the message box
তবে আপনার নামটির দরকার নেই। আপনি তাৎক্ষণিকভাবে ফোন করতে পারেন:
alert( function(x) { return x+2; } (7) ); // should print 9 in the message box
এলআইএসপিতে ল্যাম্বডাস এই জাতীয়ভাবে তৈরি করা হয়:
(lambda (x) (+ x 2))
এবং আপনি অবিলম্বে একটি প্যারামিটারে প্রয়োগ করে এমন ল্যাম্বডাকে কল করতে পারেন:
( (lambda (x) (+ x 2)) 7 )
যেমনটি আমি বলেছি, ল্যাম্বডা বিমূর্ততা যা করে তা হ'ল এটির প্রতিক্রিয়ার মধ্যে একটি প্রতীককে আবদ্ধ করে রাখে , যাতে এটি একটি বিকল্প পরামিতি হয়ে যায় । যেমন একটি প্রতীক বাউন্ড বলা হয় । তবে অভিব্যক্তিতে যদি অন্য চিহ্ন থাকে? উদাহরণস্বরূপ: λx.x/y+2
। এই অভিব্যক্তিটিতে, প্রতীকটি x
তার λx.
আগে লাম্বদা বিমূর্তনের দ্বারা আবদ্ধ । তবে অন্য প্রতীকটি, y
আবদ্ধ নয় - এটি নিখরচায় । এটি কী এবং এটি কোথা থেকে এসেছে তা আমরা জানি না, সুতরাং আমরা এর অর্থ কী এবং এটি কোন মূল্যকে উপস্থাপন করে তা আমরা জানি না এবং তাই এর y
অর্থ কী তা খুঁজে না পাওয়া পর্যন্ত আমরা এই অভিব্যক্তিটিকে মূল্যায়ন করতে পারি না ।
প্রকৃতপক্ষে, অন্য দুটি চিহ্নের সাথে একই হয়, 2
এবং +
। এটি ঠিক যে আমরা এই দুটি চিহ্নের সাথে এতটাই পরিচিত যে আমরা সাধারণত ভুলে যাই যে কম্পিউটার সেগুলি জানে না এবং কোথাও এগুলি সংজ্ঞায়িত করে তাদের অর্থ কী তা আমাদের বলতে হবে, যেমন একটি লাইব্রেরি বা ভাষায়।
আপনি অভিব্যক্তির বাইরে, এর "পার্শ্ববর্তী প্রসঙ্গে", যাকে এর পরিবেশ বলা হয় এর বাইরে অন্য কোথাও নির্ধারিত নিখরচায় প্রতীকগুলি ভাবতে পারেন । পরিবেশটি একটি বৃহত্তর অভিব্যক্তি হতে পারে যে এই অভিব্যক্তিটি একটি অংশ (যেমন কুই-গন জিন বলেছেন: "এখানে সর্বদা একটি বড় মাছ থাকে";)), বা কোনও গ্রন্থাগারে বা ভাষায় ( আদিম হিসাবে )।
এটি আমাদের ল্যাম্বদা এক্সপ্রেশন দুটি বিভাগে বিভক্ত করতে দেয়:
আপনি পরিবেশ সরবরাহ করে একটি মুক্ত ল্যাম্বডা এক্সপ্রেশন বন্ধ করতে পারেন , যা এই সমস্ত নিদর্শনকে কিছু মানকে আবদ্ধ করে সংজ্ঞায়িত করে (যা সংখ্যা, স্ট্রিং, বেনাম ফাংশন ওরফে ল্যাম্বডাস যাই হোক না কেন…)।
এবং এখানে আসে অবসান অংশ: অবসান একটি এর ল্যামডা অভিব্যক্তি বাইরের প্রসঙ্গ (পরিবেশ) যে মান দিতে সংজ্ঞায়িত চিহ্ন এই বিশেষ সেট বিনামূল্যে প্রতীক এই মত প্রকাশের জন্য, সেগুলিকে আর অ বিনামূল্যে উপার্জন। এটি একটি খোলা ল্যাম্বডা এক্সপ্রেশনকে পরিণত করে, যেখানে এখনও কিছু "অপরিজ্ঞাত" নিখরচায় চিহ্ন রয়েছে, এটি একটি বন্ধ করে দেওয়া হয়েছে , যার কোনও মুক্ত চিহ্ন নেই।
উদাহরণস্বরূপ, যদি আপনার নীচের ল্যাম্বডা এক্সপ্রেশন থাকে:, λx.x/y+2
প্রতীকটি x
আবদ্ধ, যখন প্রতীকটি y
মুক্ত, সুতরাং অভিব্যক্তিটি open
মূল্যায়ন করা যায় না যতক্ষণ না আপনি যদি না বলতে চান তবে কী y
(এবং এর সাথে একই +
এবং 2
এটিও মুক্ত)। তবে ধরুন আপনারও এমন পরিবেশ রয়েছে :
{ y: 3,
+: [built-in addition],
2: [built-in number],
q: 42,
w: 5 }
এই পরিবেশ সমস্ত "undefined" (বিনামূল্যে) আমাদের ল্যামডা অভিব্যক্তি থেকে প্রতীক জন্য সরবরাহ সংজ্ঞা ( y
, +
, 2
), এবং বিভিন্ন অতিরিক্ত চিহ্ন ( q
, w
)। আমাদের যে সংকেতগুলি সংজ্ঞায়িত করতে হবে তা হ'ল পরিবেশের এই উপসেট:
{ y: 3,
+: [built-in addition],
2: [built-in number] }
এবং এটি হ'ল আমাদের ল্যাম্বদা এক্সপ্রেশন বন্ধ করে দেওয়া:>
অন্য কথায়, এটি একটি খোলা ল্যাম্বদা এক্সপ্রেশন বন্ধ করে। এই যেখানে নাম অবসান প্রথম স্থানে থেকে এসেছিলেন, এবং এই কারণেই এই থ্রেড এত লোক এর উত্তর বেশ সঠিক নয়: পি
ঠিক আছে, সান / ওরাকল, মাইক্রোসফ্ট, গুগল ইত্যাদির কর্পোরেট বিপণনকারীদের দোষ দেওয়া হবে, কারণ এগুলিই তাদের ভাষাগুলিতে এই নির্মাণগুলি বলে (জাভা, সি #, গো ইত্যাদি)। তারা প্রায়শই "ক্লোজার" নামে ডাকে যা কেবল ল্যাম্বডাস বলে মনে হয়। বা তারা লেক্সিকাল স্কোপিং বাস্তবায়নের জন্য তারা একটি নির্দিষ্ট কৌশলকে "ক্লোজারস" বলে ডাকে, এটি হ'ল কোনও ফাংশন তার বাহ্যিক স্কোপে সংজ্ঞা দেওয়ার সময় যে পরিবর্তনগুলি অ্যাক্সেস করতে পারে তা সত্য। তারা প্রায়শই বলে যে ফাংশনটি এই ভেরিয়েবলগুলিকে "আবদ্ধ" করে, এটি বাইরের ফাংশনটি সম্পাদন শেষ হওয়ার পরে ধ্বংস হওয়ার হাত থেকে বাঁচাতে তাদের কিছু ডেটা স্ট্রাকচারে ক্যাপচার করে। তবে এটি স্রেফ পোস্ট ফ্যাক্টাম "ফোকলোর ব্যুৎপত্তি" এবং বিপণন যা কেবল বিষয়গুলিকে আরও বিভ্রান্ত করে তোলে,
এবং এটি আরও খারাপ কারণ এই যে তারা যা বলে তাতে সবসময় কিছুটা সত্য থাকে, যা আপনাকে এটিকে সহজেই মিথ্যা হিসাবে খারিজ করতে দেয় না: পি আমাকে ব্যাখ্যা করতে দিন:
যদি আপনি এমন কোনও ভাষা প্রয়োগ করতে চান যা ল্যাম্বডাসকে প্রথম-শ্রেণীর নাগরিক হিসাবে ব্যবহার করে, আপনি তাদের আশেপাশের প্রসঙ্গে সংজ্ঞায়িত চিহ্নগুলি ব্যবহার করার অনুমতি দিতে হবে (এটি আপনার ল্যাম্বডাসে মুক্ত ভেরিয়েবল ব্যবহার করার জন্য)। আশেপাশের ফাংশনটি ফিরে আসার পরেও এই চিহ্নগুলি অবশ্যই সেখানে থাকতে হবে। সমস্যাটি হ'ল এই চিহ্নগুলি ফাংশনের কিছু স্থানীয় স্টোরেজ (সাধারণত কল স্ট্যাকের সাথে) আবদ্ধ থাকে, যা ফাংশন ফিরে আসার পরে আর থাকবে না। সুতরাং, কোনও ল্যাম্বডা আপনার প্রত্যাশা অনুযায়ী কাজ করার জন্য, আপনাকে কোনওভাবেই এই সমস্ত বিনামূল্যে ভেরিয়েবলগুলি তার বাহ্যিক প্রসঙ্গ থেকে "ক্যাপচার" করতে হবে এবং বাইরের প্রসঙ্গটি চলে গেলেও পরে সংরক্ষণ করতে হবে। এটি হ'ল, আপনাকে বন্ধটি সন্ধান করতে হবেআপনার ল্যাম্বদা (এই সমস্ত বাহ্যিক ভেরিয়েবলগুলি এটি ব্যবহার করে) এবং এটি অন্য কোথাও সংরক্ষণ করুন (হয় অনুলিপি তৈরি করে, বা তাদের জন্য সামনে প্রস্তুত করার জন্য, স্ট্যাকের বাইরে অন্য কোথাও)। এই লক্ষ্য অর্জনের জন্য আপনি যে আসল পদ্ধতিটি ব্যবহার করেন তা হ'ল আপনার ভাষার "প্রয়োগের বিশদ"। এখানে গুরুত্বপূর্ণ কীটি হ'ল বন্ধ , যা আপনার ল্যাম্বদার পরিবেশ থেকে মুক্ত ভেরিয়েবলগুলির সেট যা কোথাও সংরক্ষণ করা দরকার।
ক্লোজারটিকে "ক্লোজার" হিসাবে রূপান্তরিত করার জন্য লোকেরা তাদের ভাষার বাস্তবায়নে যে প্রকৃত ডেটা স্ট্রাকচার ব্যবহার করে তা কল করতে খুব বেশি সময় নেয়নি। কাঠামোটি সাধারণত এ জাতীয় কিছু দেখায়:
Closure {
[pointer to the lambda function's machine code],
[pointer to the lambda function's environment]
}
এবং এই ডেটা স্ট্রাকচারগুলি ল্যাম্বডাস উপস্থাপনের জন্য অন্যান্য ফাংশনগুলিতে পরামিতি হিসাবে ফাংশনগুলি থেকে ফিরে আসে এবং ভেরিয়েবলগুলিতে সংরক্ষণ করা হয় এবং তাদের সংলগ্ন পরিবেশের পাশাপাশি মেশিন কোডটিকে সেই প্রসঙ্গে চালানোর অনুমতি দেয়। কিন্তু এটা শুধু একটি উপায় (অনেক এক) এর বাস্তবায়ন অবসান না অবসান নিজেই।
যেমন আমি উপরে ব্যাখ্যা করেছি, ল্যাম্বডা এক্সপ্রেশনটি বন্ধ করা তার পরিবেশের সংজ্ঞাগুলির উপসেট যা সেই ল্যাম্বডা এক্সপ্রেশনটিতে থাকা মুক্ত ভেরিয়েবলগুলিকে মান দেয়, কার্যকরভাবে এক্সপ্রেশনটি বন্ধ করে দেয় (একটি উন্মুক্ত ল্যাম্বডা এক্সপ্রেশন, যা এখনও মূল্যায়ন করা যায় না) একটি বদ্ধ ল্যাম্বডা এক্সপ্রেশন, যা তখন মূল্যায়ন করা যায়, যেহেতু এতে থাকা সমস্ত চিহ্নগুলি এখন সংজ্ঞায়িত করা হয়েছে)।
এ জাতীয় ধারণাগুলির আসল মূল সম্পর্কে অজানা প্রোগ্রামার এবং ভাষা বিক্রেতাদের আর কিছু যে কেবল "কার্গো কাল্ট" এবং "ভু-ডু যাদু"।
আমি যে আপনার প্রশ্নের উত্তর আশা করি। তবে আপনার যদি কোনও ফলো-আপ প্রশ্ন থাকে তবে তাদেরকে মন্তব্যগুলিতে বিনা দ্বিধায় জিজ্ঞাসা করুন এবং আমি আরও ভাল করে ব্যাখ্যা করার চেষ্টা করব।
যখন বেশিরভাগ লোকেরা ফাংশনগুলি সম্পর্কে চিন্তা করে , তারা নামযুক্ত ফাংশনগুলি সম্পর্কে চিন্তা করে :
function foo() { return "This string is returned from the 'foo' function"; }
এগুলি অবশ্যই নামে ডাকা হয়:
foo(); //returns the string above
ল্যাম্বদা এক্সপ্রেশন সহ আপনার বেনামে ফাংশন থাকতে পারে :
@foo = lambda() {return "This is returned from a function without a name";}
উপরের উদাহরণ সহ, আপনি যে ভেরিয়েবলটি নির্ধারিত হয়েছিল তার মাধ্যমে ল্যাম্বডাকে কল করতে পারেন:
foo();
ভেরিয়েবলগুলিকে বেনামে ফাংশন নির্ধারণের চেয়ে আরও দরকারী, তবে তাদের উচ্চতর-ক্রিয়াকলাপগুলি থেকে বা এগুলি প্রদান করা হয়, অর্থাত্ যে ফাংশনগুলি অন্যান্য ফাংশন গ্রহণ করে / ফেরত দেয়। এই ক্ষেত্রে অনেক ক্ষেত্রে, একটি ফাংশন নামকরণ অপ্রয়োজনীয়:
function filter(list, predicate)
{ @filteredList = [];
for-each (@x in list) if (predicate(x)) filteredList.add(x);
return filteredList;
}
//filter for even numbers
filter([0,1,2,3,4,5,6], lambda(x) {return (x mod 2 == 0)});
একটি বন্ধকরণ একটি নামযুক্ত বা বেনামি ফাংশন হতে পারে, তবে এটি যখন ফাংশনটি সংজ্ঞায়িত করা হয় এমন স্ক্র্যাপের ভেরিয়েবলগুলিকে "ক্লোজর" করে হিসাবে পরিচিত করা হয়, অর্থাৎ বন্ধটি এখনও ব্যবহৃত হয় এমন কোনও বাহ্যিক ভেরিয়েবলের সাথে পরিবেশকে বোঝায় যা ব্যবহৃত হয় নিজেই বন্ধ এখানে একটি নামকরণ বন্ধ রয়েছে:
@x = 0;
function incrementX() { x = x + 1;}
incrementX(); // x now equals 1
এটি অনেকটা মনে হচ্ছে না তবে কি যদি এই সমস্ত কিছু অন্য ফাংশনে থাকে এবং আপনি incrementX
কোনও বাহ্যিক ফাংশনে চলে যান?
function foo()
{ @x = 0;
function incrementX()
{ x = x + 1;
return x;
}
return incrementX;
}
@y = foo(); // y = closure of incrementX over foo.x
y(); //returns 1 (y.x == 0 + 1)
y(); //returns 2 (y.x == 1 + 1)
ফাংশনাল প্রোগ্রামিংয়ে আপনি এভাবে স্টেটফুল অবজেক্টস পান। যেহেতু "ইনক্রিমেন্টএক্স" নামকরণের প্রয়োজন নেই, আপনি এই ক্ষেত্রে একটি ল্যাম্বডা ব্যবহার করতে পারেন:
function foo()
{ @x = 0;
return lambda()
{ x = x + 1;
return x;
};
}
সমস্ত ক্লোজারগুলি ল্যাম্বডাস নয় এবং সমস্ত ল্যাম্বডাস ক্লোজার নয়। উভয়ই ফাংশন, তবে আমরা যেভাবে জানার জন্য অভ্যস্ত তা প্রয়োজনীয়ভাবে নয়।
একটি ল্যাম্বডা মূলত একটি ফাংশন যা ডিক্লারিং ফাংশনগুলির মান পদ্ধতির চেয়ে ইনলাইন সংজ্ঞায়িত করা হয়। ল্যাম্বডাস প্রায়শই বস্তু হিসাবে প্রায় পাস করা যেতে পারে।
একটি ক্লোজার এমন একটি ফাংশন যা তার দেহের বাহ্যিক ক্ষেত্রগুলিকে উল্লেখ করে তার চারপাশের রাজ্যটি আবদ্ধ করে। বদ্ধ রাষ্ট্রটি বন্ধের অনুরোধ জুড়ে রয়েছে।
কোনও অবজেক্ট-ভিত্তিক ভাষায় ক্লোজারগুলি সাধারণত অবজেক্টের মাধ্যমে সরবরাহ করা হয়। তবে কিছু ওও ভাষা (উদাহরণস্বরূপ সি #) বিশেষ কার্যকারিতা বাস্তবায়িত করে যা বিশুদ্ধরূপে কার্যকরী ভাষা (যেমন লিস্প) দ্বারা প্রদত্ত ক্লোজারগুলির সংজ্ঞার নিকটবর্তী যেখানে রাষ্ট্রকে ঘিরে রাখার মতো অবজেক্ট নেই।
মজার বিষয় হ'ল সি # তে ল্যাম্বডাস এবং ক্লোজারগুলির প্রবর্তন কার্যকরী প্রোগ্রামিংকে মূলধারার ব্যবহারের আরও কাছাকাছি নিয়ে আসে।
এটি এর মতোই সহজ: ল্যাম্বদা একটি ভাষা নির্মাণ, অর্থাত্ বেনাম ফাংশনগুলির জন্য কেবল বাক্য গঠন; ক্লোজার হ'ল এটি বাস্তবায়নের একটি কৌশল - বা কোনও বিষয় প্রথম শ্রেণীর ফাংশন, নাম বা বেনামে।
আরও স্পষ্টভাবে বলতে গেলে , একটি ক্লোজার হ'ল রান - টাইমে প্রথম শ্রেণির ফাংশনটি কীভাবে তার "কোড" এর জুড়ি এবং সেই কোডটিতে ব্যবহৃত সমস্ত অ-স্থানীয় ভেরিয়েবলের উপর একটি পরিবেশ "ক্লোজিং" হিসাবে উপস্থাপিত হয়। এই ভাবে, সেই পরিবর্তনগুলি এখনও অ্যাক্সেসযোগ্য এমনকি যখন বাহ্যিক স্কোপগুলি যেখানে উত্সিত হয়েছে ইতোমধ্যে বাইরে চলে গেছে।
দুর্ভাগ্যক্রমে, অনেকগুলি ভাষা এখানে রয়েছে যা প্রথম শ্রেণির মান হিসাবে ফাংশন সমর্থন করে না, বা কেবল পঙ্গু আকারে তাদের সমর্থন করে। সুতরাং লোকেরা প্রায়শই "আসল জিনিস" পার্থক্য করতে "ক্লোজার" শব্দটি ব্যবহার করে।
প্রোগ্রামিং ভাষার দৃষ্টিভঙ্গি থেকে এগুলি সম্পূর্ণ দুটি ভিন্ন জিনিস।
মূলত একটি টিউরিং সম্পূর্ণ ভাষার জন্য আমাদের কেবল খুব সীমিত উপাদানগুলির প্রয়োজন, যেমন বিমূর্তি, প্রয়োগ এবং হ্রাস। বিমূর্ততা এবং অ্যাপ্লিকেশনটি আপনি ল্যামডবা এক্সপ্রেশনটি তৈরি করতে পারে এবং হ্রাস ল্যাম্বডা এক্সপ্রেশনটির অর্থ নির্ধারণ করে provides
ল্যাম্বদা এমন একটি উপায় সরবরাহ করে যাতে আপনি গণনা প্রক্রিয়াটি বিমূর্ত করতে পারেন। উদাহরণস্বরূপ, দুটি সংখ্যার যোগফল গণনা করতে, এমন একটি প্রক্রিয়া যা দুটি প্যারামিটার x, y এবং x + y প্রদান করে তা বিমূর্ত করা যেতে পারে। স্কিম, আপনি এটি লিখতে পারেন
(lambda (x y) (+ x y))
আপনি প্যারামিটারগুলির নাম পরিবর্তন করতে পারেন, তবে এটি যে কার্যটি সম্পন্ন করে তা পরিবর্তন হয় না। প্রায় সমস্ত প্রোগ্রামিং ভাষায়, আপনি ল্যাম্বডা এক্সপ্রেশনটিকে একটি নাম দিতে পারেন, যার নাম ফাংশন। তবে তেমন কোনও পার্থক্য নেই, এগুলি কেবলমাত্র সিনট্যাক্স চিনির হিসাবে ধারণাগত হিসাবে বিবেচনা করা যেতে পারে।
ঠিক আছে, এখন ভেবে দেখুন কীভাবে এটি বাস্তবায়ন করা যায়। যখনই আমরা কিছু এক্সপ্রেশনগুলিতে ল্যাম্বডা এক্সপ্রেশন প্রয়োগ করি
((lambda (x y) (+ x y)) 2 3)
মূল্যায়নের জন্য আমরা বাক্সগুলির সাথে পরামিতিগুলি সহজেই প্রতিস্থাপন করতে পারি। এই মডেলটি ইতিমধ্যে খুব শক্তিশালী। তবে এই মডেলটি আমাদের প্রতীকগুলির মানগুলি পরিবর্তন করতে সক্ষম করে না, উদাহরণস্বরূপ আমরা স্থিতির পরিবর্তনের নকল করতে পারি না। এইভাবে আমাদের আরও জটিল মডেল দরকার। এটি সংক্ষিপ্ত করার জন্য, যখনই আমরা ল্যাম্বডা এক্সপ্রেশনটির অর্থ গণনা করতে চাই, আমরা প্রতীকের জোড় এবং সংশ্লিষ্ট মানটিকে একটি পরিবেশে (বা টেবিল) রাখি। তারপরে বাকী (+ xy) সারণীতে সংশ্লিষ্ট চিহ্নগুলি দেখে মূল্যায়ন করা হয়। এখন যদি আমরা সরাসরি পরিবেশে চালনা করার জন্য কিছু আদিম সরবরাহ করি তবে আমরা স্থিতির পরিবর্তনগুলি মডেল করতে পারি!
এই পটভূমি সহ, এই ফাংশনটি পরীক্ষা করুন:
(lambda (x y) (+ x y z))
আমরা জানি যে যখন আমরা ল্যাম্বডা এক্সপ্রেশনটি মূল্যায়ন করি তখন xy একটি নতুন টেবিলে আবদ্ধ হবে। তবে কিভাবে এবং কোথায় আমরা z আপ আপ দেখতে পারেন? আসলে z কে ফ্রি ভেরিয়েবল বলা হয়। বাহ্যিক পরিবেশ থাকতে হবে যা z থাকে। অন্যথায় এক্স x এবং y দ্বারা বাঁধার দ্বারা অভিব্যক্তির অর্থ নির্ধারণ করা যায় না। এটি পরিষ্কার করার জন্য, আপনি স্কিমের নীচে কিছু লিখতে পারেন:
((lambda (z) (lambda (x y) (+ x y z))) 1)
সুতরাং z বহিরাগত টেবিলে 1 তে আবদ্ধ হবে। আমরা এখনও একটি ফাংশন পাই যা দুটি পরামিতি গ্রহণ করে তবে এর আসল অর্থটি বাইরের পরিবেশের উপরও নির্ভর করে। অন্য কথায় বাইরের পরিবেশ মুক্ত ভেরিয়েবলগুলিতে বন্ধ হয়। সেটটির সাহায্যে, আমরা ফাংশনটিকে রাষ্ট্রীয় করে তুলতে পারি, অর্থাৎ এটি গণিতের অর্থে কোনও ফাংশন নয়। এটি কী ফিরিয়ে দেয় তা কেবল ইনপুটের উপর নির্ভর করে না, পাশাপাশি zও নির্ভর করে।
এটি এমন একটি বিষয় যা আপনি ইতিমধ্যে খুব ভাল জানেন, অবজেক্টগুলির একটি পদ্ধতি প্রায়শই সবসময় অবজেক্টের অবস্থার উপর নির্ভর করে। এ কারণেই কিছু লোক বলে "ক্লোজারগুলি দরিদ্র মানুষের জিনিস।"
আমি সেই প্রকল্পের কারণে ধারণাগুলি চিত্রিত করার জন্য স্কিম ব্যবহার করি এটি প্রাথমিক ভাষাগুলির মধ্যে একটি যা সত্যিকারের বন্ধ হয়ে গেছে। এখানকার সমস্ত উপকরণ এসআইসিপি অধ্যায় 3 এ আরও ভালভাবে উপস্থাপিত হয়েছে।
সংক্ষেপে বলতে গেলে ল্যাম্বদা এবং ক্লোজারটি সত্যিই আলাদা ধারণা। একটি ল্যাম্বদা একটি ফাংশন। একটি বন্ধন লাম্বদা এবং এটি সম্পর্কিত পরিবেশ যা ল্যাম্বডা বন্ধ করে দেয় pair
ধারণাটি উপরে বর্ণিত হিসাবে একই, তবে আপনি যদি পিএইচপি ব্যাকগ্রাউন্ড থেকে হন তবে পিএইচপি কোড ব্যবহার করে এটি আরও ব্যাখ্যা করে।
$input = array(1, 2, 3, 4, 5);
$output = array_filter($input, function ($v) { return $v > 2; });
ফাংশন ($ v) {রিটার্ন $ v> 2; ল্যাম্বদা ফাংশন সংজ্ঞা। এমনকি আমরা এটিকে একটি চলকতেও সঞ্চয় করতে পারি, তাই এটি পুনরায় ব্যবহারযোগ্য হতে পারে:
$max = function ($v) { return $v > 2; };
$input = array(1, 2, 3, 4, 5);
$output = array_filter($input, $max);
এখন, আপনি যদি ফিল্টার করা অ্যারেটিতে অনুমোদিত সর্বোচ্চ নম্বরটি পরিবর্তন করতে চান? আপনাকে অন্য ল্যাম্বদা ফাংশন লিখতে হবে বা একটি ক্লোজার তৈরি করতে হবে (পিএইচপি 5.3):
$max_comp = function ($max) {
return function ($v) use ($max) { return $v > $max; };
};
$input = array(1, 2, 3, 4, 5);
$output = array_filter($input, $max_comp(2));
ক্লোজার হ'ল এমন একটি ফাংশন যা তার নিজস্ব পরিবেশে মূল্যায়ন করা হয়, যার ফাংশন ডাকা হলে এটিতে এক বা একাধিক বাউন্ড ভেরিয়েবলগুলি অ্যাক্সেস করা যায়। এগুলি ক্রিয়ামূলক প্রোগ্রামিং জগত থেকে আসে, যেখানে নাটকটিতে প্রচুর ধারণা রয়েছে। বন্ধগুলি ল্যাম্বডা ফাংশনের মতো, তবে বুদ্ধিমানের দিক থেকে তারা বুদ্ধিমানভাবে যেখানে বাইরের পরিবেশ থেকে ক্লোজারটি সংজ্ঞায়িত করা হয়েছে তার সাথে ভেরিয়েবলের সাথে যোগাযোগের ক্ষমতা রাখে sense
এখানে পিএইচপি বন্ধের একটি সহজ উদাহরণ:
$string = "Hello World!";
$closure = function() use ($string) { echo $string; };
$closure();
এই প্রশ্নটি পুরানো এবং অনেক উত্তর পেয়েছে।
এখন জাভা 8 এবং অফিশিয়াল ল্যাম্বদা যা আনুষ্ঠানিকভাবে বন্ধ প্রকল্পগুলি, এটি প্রশ্নটিকে পুনরুদ্ধার করে।
জাভা প্রসঙ্গে উত্তর ( ল্যাম্বডাস এবং ক্লোজারগুলির মাধ্যমে - পার্থক্য কী? ):
"ক্লোজারটি এমন একটি ল্যাম্বডা ভাব যা এমন পরিবেশের সাথে যুক্ত যা তার প্রতিটি মুক্ত ভেরিয়েবলকে একটি মানের সাথে আবদ্ধ করে s
সোজা কথায়, ক্লোজার হ'ল সুযোগ সম্পর্কে কৌশল, ল্যাম্বডা একটি বেনামি কার্য। আমরা লাম্বদা দিয়ে আরও বন্ধুত্বের সাথে ক্লোজার উপলব্ধি করতে পারি এবং লাম্বদা প্রায়শই একটি উচ্চতর ফাংশনে স্থানান্তরিত প্যারামিটার হিসাবে ব্যবহৃত হয়
একটি ল্যাম্বডা এক্সপ্রেশনটি কেবল একটি বেনামে ফাংশন। সরল জাভাতে, উদাহরণস্বরূপ, আপনি এটি এটি লিখতে পারেন:
Function<Person, Job> mapPersonToJob = new Function<Person, Job>() {
public Job apply(Person person) {
Job job = new Job(person.getPersonId(), person.getJobDescription());
return job;
}
};
যেখানে ক্লাস ফাংশনটি স্রেফ জাভা কোডে নির্মিত। এখন আপনি mapPersonToJob.apply(person)
এটি ব্যবহার করতে কোথাও কল করতে পারেন। শুধু একটি উদাহরণ thats। একটি ল্যাম্বডা এর জন্য সিনট্যাক্সের আগে রয়েছে। লাম্বদাস এটির জন্য একটি শর্ট কাট।
বন্ধ:
একটি লাম্বদা একটি ক্লোজার হয়ে যায় যখন এটি এই সুযোগের বাইরে চলকগুলিতে অ্যাক্সেস করতে পারে। আমার ধারণা আপনি এটির যাদু বলতে পারেন, এটি যাদুতে এটি তৈরি করা হয়েছিল এমন পরিবেশের চারপাশে গুটিয়ে রাখতে পারে এবং এর ক্ষেত্রের বাইরে ভেরিয়েবলগুলি ব্যবহার করতে পারে (বাহ্যিক স্কোপ। সুতরাং স্পষ্ট করে বলতে গেলে, একটি ক্লোজার মানে একটি ল্যাম্বডা তার আউট স্কোপে অ্যাক্সেস করতে পারে।
কোটলিনে, একটি ল্যাম্বদা সর্বদা এটি বন্ধ করে (তার বহিরাগত স্কোপের মধ্যে থাকা ভেরিয়েবলগুলি) অ্যাক্সেস করতে পারে
কোনও ফাংশন বাহ্যিক চলক ব্যবহার করে না অপারেশন সঞ্চালনের জন্য এটি নির্ভর করে।
বাহ্যিক ভেরিয়েবল - একটি ফাংশনের সুযোগের বাইরে নির্ধারিত ভেরিয়েবলগুলি।
ল্যাম্বডা এক্সপ্রেশনগুলি রাষ্ট্রহীন কারণ এটি পরামিতিগুলি, অভ্যন্তরীণ ভেরিয়েবলগুলি বা অপারেশন সম্পাদনের জন্য ধ্রুবকের উপর নির্ভর করে।
Function<Integer,Integer> lambda = t -> {
int n = 2
return t * n
}
বন্ধগুলি রাষ্ট্রকে ধরে রাখে কারণ এটি অপারেশন সম্পাদনের জন্য প্যারামিটার এবং ধ্রুবক সহ বাহ্যিক ভেরিয়েবল (অর্থাত্ ফাংশন বডির স্কোপের বাইরে সংজ্ঞাযুক্ত ভেরিয়েবল) ব্যবহার করে।
int n = 2
Function<Integer,Integer> closure = t -> {
return t * n
}
যখন জাভা ক্লোজার তৈরি করে, এটি ভেরিয়েবলটিকে ফাংশনটির সাথে রাখে যাতে এটি অন্য ফাংশনগুলিতে পাস করার পরে বা অন্য কোথাও ব্যবহার করার পরে তা উল্লেখ করা যায়।