C ++ میں لیمبڈا ایکسپریشنز۔

Lambda Expressions C



لیمبڈا ایکسپریشن کیوں؟

مندرجہ ذیل بیان پر غور کریں:

intmyInt= 52۔؛

یہاں ، myInt ایک شناخت کنندہ ہے ، ایک قدر ہے۔ 52 ایک لفظی ، ایک قیمت ہے۔ آج ، کسی فنکشن کو خاص طور پر کوڈ کرنا اور اسے 52 کی پوزیشن میں رکھنا ممکن ہے۔ ایسے فنکشن کو لیمبڈا ایکسپریشن کہا جاتا ہے۔ مندرجہ ذیل مختصر پروگرام پر بھی غور کریں:







#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intfn(intکے ذریعے)

{

intجواب=کے ذریعے+ ؛

واپسیجواب؛

}


intمرکزی()

{

fn()؛



واپسی ؛

}

آج ، یہ ممکن ہے کہ کسی فنکشن کو خاص طور پر کوڈ کیا جائے اور اسے فنکشن کال ، fn (5) کی دلیل 5 کی پوزیشن میں رکھا جائے۔ اس طرح کے فنکشن کو لیمبڈا ایکسپریشن کہا جاتا ہے۔ اس پوزیشن میں لیمبڈا ایکسپریشن (فنکشن) ایک قیمت ہے۔



سٹرنگ لیٹرل کے علاوہ کوئی بھی لفظی قیمت ہے۔ لیمبڈا اظہار ایک خاص فنکشن ڈیزائن ہے جو کوڈ میں لفظی طور پر فٹ ہوگا۔ یہ ایک گمنام (بے نام) فنکشن ہے۔ یہ مضمون نئے C ++ بنیادی اظہار کی وضاحت کرتا ہے ، جسے لیمبڈا ایکسپریشن کہتے ہیں۔ C ++ میں بنیادی علم اس مضمون کو سمجھنے کی ضرورت ہے۔



مضمون کا مواد۔

لیمبڈا اظہار کی مثال۔

مندرجہ ذیل پروگرام میں ، ایک فنکشن ، جو لیمبڈا ایکسپریشن ہے ، ایک متغیر کو تفویض کیا گیا ہے:





#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

آٹوfn= [](intرک جاؤ)

{

intجواب=رک جاؤ+ ؛

واپسیجواب؛

}؛


intمرکزی()

{

آٹومختلف=fn()؛

لاگت <<مختلف<< 'n'؛


واپسی ؛

}

پیداوار یہ ہے:

مرکزی () فنکشن کے باہر ، متغیر ہے ، fn۔ اس کی قسم آٹو ہے۔ اس صورت حال میں آٹو کا مطلب یہ ہے کہ اصل قسم ، جیسے int یا float ، اسائنمنٹ آپریٹر (=) کے دائیں آپریینڈ سے متعین ہوتی ہے۔ اسائنمنٹ آپریٹر کے دائیں جانب لیمبڈا ایکسپریشن ہے۔ لیمبڈا ایکسپریشن سابقہ ​​ریٹرن ٹائپ کے بغیر ایک فنکشن ہے۔ مربع بریکٹ کے استعمال اور پوزیشن کو نوٹ کریں ، []۔ فنکشن 5 ، ایک انٹ واپس کرتا ہے ، جو fn کی قسم کا تعین کرے گا۔



مرکزی () فنکشن میں ، بیان ہے:

آٹومختلف=fn()؛

اس کا مطلب ہے ، fn باہر main () ، ایک فنکشن کے لیے شناخت کنندہ کے طور پر ختم ہوتا ہے۔ اس کے مضمر پیرامیٹرز لیمبڈا اظہار کے ہیں۔ variab کی قسم آٹو ہے۔

نوٹ کریں کہ لیمبڈا اظہار ایک سیمیکولن کے ساتھ ختم ہوتا ہے ، جیسے کلاس یا ڈھانچے کی تعریف ، سیمیکولن کے ساتھ ختم ہوتا ہے۔

مندرجہ ذیل پروگرام میں ، ایک فنکشن ، جو ایک لیمبڈا ایکسپریشن ہے جو 5 کی قیمت لوٹاتا ہے ، دوسرے فنکشن کی دلیل ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

باطلدوسری(intنمبر 1 ،int (*پی ٹی آر)(int))

{

intنمبر 2= (*پی ٹی آر)()؛

لاگت <<نمبر 1<< '' <<نمبر 2<< 'n'؛

}


intمرکزی()

{

دوسری(،[](intرک جاؤ)

{

intجواب=رک جاؤ+ ؛

واپسیجواب؛

})؛


واپسی ؛
}

پیداوار یہ ہے:

چار پانچ

یہاں دو افعال ہیں ، لیمبڈا ایکسپریشن اور دوسرا ایف این () فنکشن۔ لیمبڈا ایکسپریشن otherfn () کی دوسری دلیل ہے ، جسے main () کہا جاتا ہے۔ نوٹ کریں کہ لیمبڈا فنکشن (اظہار) اس کال میں سیمیکولن کے ساتھ ختم نہیں ہوتا ہے کیونکہ ، یہاں ، یہ ایک دلیل ہے (اسٹینڈ اکیلے فنکشن نہیں)۔

لیمبڈا فنکشن پیرامیٹر otherfn () فنکشن کی تعریف میں ایک فنکشن کی طرف اشارہ کرتا ہے۔ پوائنٹر کا نام ہے ، پی ٹی آر۔ نام ، پی ٹی آر ، لیمبڈا فنکشن کو کال کرنے کے لئے دوسری ایف این () تعریف میں استعمال ہوتا ہے۔

بیان،

intنمبر 2= (*پی ٹی آر)()؛

otherfn () تعریف میں ، یہ لیمبڈا فنکشن کو 2 کی دلیل کے ساتھ کال کرتا ہے ، کال کی ریٹرن ویلیو ، '(*ptr) (2)' لیمبڈا فنکشن سے ، نمبر 2 کو تفویض کی گئی ہے۔

مذکورہ پروگرام یہ بھی ظاہر کرتا ہے کہ لیمبڈا فنکشن کو C ++ کال بیک فنکشن اسکیم میں کیسے استعمال کیا جا سکتا ہے۔

لیمبڈا اظہار کے حصے۔

ایک عام لیمبڈا فنکشن کے حصے مندرجہ ذیل ہیں۔

[] () {}
  • [] گرفتاری کی شق ہے۔ اس میں اشیاء ہوسکتی ہیں۔
  • () پیرامیٹر لسٹ کے لیے ہے۔
  • {} فنکشن باڈی کے لیے ہے۔ اگر فنکشن اکیلے کھڑا ہے ، تو اسے سیمیکولن کے ساتھ ختم ہونا چاہئے۔

کیپچرز۔

لیمبڈا فنکشن کی تعریف کسی متغیر کو تفویض کی جاسکتی ہے یا کسی مختلف فنکشن کال کی دلیل کے طور پر استعمال کی جاسکتی ہے۔ اس طرح کے فنکشن کال کی تعریف ایک پیرامیٹر کے طور پر ہونی چاہیے ، ایک فنکشن کے لیے ایک پوائنٹر ، جو لیمبڈا فنکشن کی تعریف کے مطابق ہو۔

لیمبڈا فنکشن کی تعریف عام فنکشن کی تعریف سے مختلف ہے۔ یہ عالمی دائرہ کار میں ایک متغیر کو تفویض کیا جا سکتا ہے۔ یہ فنکشن تفویض سے متغیر کو دوسرے فنکشن کے اندر بھی کوڈ کیا جا سکتا ہے۔ جب گلوبل اسکوپ متغیر کو تفویض کیا جاتا ہے تو ، اس کا جسم عالمی دائرہ کار میں دیگر متغیرات دیکھ سکتا ہے۔ جب ایک عام فنکشن کی تعریف کے اندر کسی متغیر کو تفویض کیا جاتا ہے تو ، اس کا جسم فنکشن کے دائرے میں دیگر متغیرات کو صرف کیپچر شق کی مدد سے دیکھ سکتا ہے ، []۔

گرفتاری شق [] ، جسے لیمبڈا انٹروڈیوسر بھی کہا جاتا ہے ، متغیرات کو ارد گرد (فنکشن) کے دائرے سے لیمبڈا ایکسپریشن کے فنکشن باڈی میں بھیجنے کی اجازت دیتا ہے۔ لیمبڈا ایکسپریشن کے فنکشن باڈی کے بارے میں کہا جاتا ہے کہ جب وہ چیز حاصل کرتا ہے تو متغیر پر قبضہ کر لیتا ہے۔ گرفتاری شق [] کے بغیر ، متغیر کو ارد گرد کے دائرے سے لیمبڈا ایکسپریشن کے فنکشن باڈی میں نہیں بھیجا جاسکتا۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے ، مرکزی () فنکشن اسکوپ کے ساتھ ، آس پاس کے دائرہ کار کے طور پر:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛


آٹوfn= [آئی ڈی]()

{

لاگت <<آئی ڈی<< 'n'؛

}؛

fn()؛


واپسی ؛

}

آؤٹ پٹ ہے۔ . نام کے بغیر ، آئی ڈی ، [] کے اندر ، لیمبڈا ایکسپریشن نے مین () فنکشن اسکوپ کی متغیر آئی ڈی نہیں دیکھی ہوگی۔

حوالہ کے ذریعے گرفتاری۔

مذکورہ بالا مثال کیپچر شق کا استعمال قیمت کے لحاظ سے قبضہ کر رہا ہے (ذیل میں تفصیلات دیکھیں)۔ حوالہ سے قبضہ کرنے میں ، متغیر کا مقام (اسٹوریج) ، مثلا id ، آئی ڈی اوپر ، آس پاس کے دائرہ کار میں ، لیمبڈا فنکشن باڈی کے اندر دستیاب ہوتا ہے۔ لہذا ، لیمبڈا فنکشن باڈی کے اندر متغیر کی قدر کو تبدیل کرنے سے ارد گرد کے دائرے میں اسی متغیر کی قدر بدل جائے گی۔ گرفتاری کی شق میں دہرایا جانے والا ہر متغیر اس سے پہلے ایمپرسینڈ (&) کے ذریعے ہوتا ہے۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛

آٹوfn= [&آئی ڈی ،&فٹ ،&چودھری]()

{

آئی ڈی= ؛فٹ= 3.4۔؛چودھری= 'بی'؛

}؛

fn()؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< 'n'؛

واپسی ؛

}

پیداوار یہ ہے:

6 ، 3.4 ، بی۔

اس بات کی تصدیق کرتے ہوئے کہ لیمبڈا ایکسپریشن کے فنکشن باڈی کے اندر متغیر نام لیمبڈا ایکسپریشن سے باہر ایک ہی متغیر کے لیے ہیں۔

قدر کے لحاظ سے قبضہ۔

قیمت کے لحاظ سے قبضہ کرنے میں ، متغیر کے محل وقوع کی ایک کاپی ، آس پاس کے دائرے میں ، لیمبڈا فنکشن باڈی کے اندر دستیاب کی جاتی ہے۔ اگرچہ لیمبڈا فنکشن باڈی کے اندر متغیر ایک کاپی ہے ، لیکن اس کی قیمت کو ابھی جسم کے اندر تبدیل نہیں کیا جا سکتا۔ قیمت کے لحاظ سے قبضہ حاصل کرنے کے لیے ، ہر متغیر کیپچر شق میں دہرایا جاتا ہے کسی بھی چیز سے پہلے نہیں۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛

آٹوfn= [id ، ft ، ch]()

{

// id = 6 فٹ = 3.4 ch = 'B'

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< 'n'؛

}؛

fn()؛

آئی ڈی= ؛فٹ= 3.4۔؛چودھری= 'بی'؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< 'n'؛

واپسی ؛

}

پیداوار یہ ہے:

5 ، 2.3 ، اے۔

6 ، 3.4 ، بی۔

اگر تبصرہ اشارے کو ہٹا دیا جاتا ہے تو ، پروگرام مرتب نہیں ہوگا۔ مرتب کرنے والا ایک غلطی کا پیغام جاری کرے گا کہ فنکشن باڈی کی لیمبڈا ایکسپریشن کی تعریف کے اندر متغیرات کو تبدیل نہیں کیا جا سکتا۔ اگرچہ متغیرات کو لیمبڈا فنکشن کے اندر تبدیل نہیں کیا جاسکتا ، لیکن انہیں لیمبڈا فنکشن کے باہر تبدیل کیا جاسکتا ہے ، جیسا کہ مذکورہ پروگرام کا آؤٹ پٹ ظاہر کرتا ہے۔

اختلاط کیپچرز۔

حوالہ سے قبضہ اور قدر کے لحاظ سے قبضہ ملایا جا سکتا ہے ، جیسا کہ مندرجہ ذیل پروگرام سے ظاہر ہوتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛ بولbl= سچ؛


آٹوfn= [آئی ڈی ، فوٹ ،&چودھری،&bl]()

{

چودھری= 'بی'؛bl= جھوٹا؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< '،' <<bl<< 'n'؛

}؛

fn()؛


واپسی ؛

}

پیداوار یہ ہے:

5 ، 2.3 ، بی ، 0۔

جب سب پکڑے جاتے ہیں ، حوالہ سے ہوتے ہیں:

اگر پکڑے جانے والے تمام متغیرات کو حوالہ کے ذریعے پکڑا جاتا ہے ، تو گرفتاری کی شق میں صرف ایک اور کافی ہوگا۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛ بولbl= سچ؛


آٹوfn= [&]()

{

آئی ڈی= ؛فٹ= 3.4۔؛چودھری= 'بی'؛bl= جھوٹا؛

}؛

fn()؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< '،' <<bl<< 'n'؛


واپسی ؛

}

پیداوار یہ ہے:

6 ، 3.4 ، بی ، 0۔

اگر کچھ متغیرات کو حوالہ کے ذریعے اور دیگر کو قدر کے لحاظ سے پکڑنا ہے ، تو ایک اور تمام حوالوں کی نمائندگی کرے گا ، اور باقی ہر ایک کو کسی بھی چیز سے پہلے نہیں کیا جائے گا ، جیسا کہ مندرجہ ذیل پروگرام دکھاتا ہے:

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛ بولbl= سچ؛


آٹوfn= [&، آئی ڈی ، فٹ]()

{

چودھری= 'بی'؛bl= جھوٹا؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< '،' <<bl<< 'n'؛

}؛

fn()؛


واپسی ؛

}

پیداوار یہ ہے:

5 ، 2.3 ، بی ، 0۔

نوٹ کریں کہ & اکیلے (یعنی ، اور شناخت کنندہ کے بعد نہیں) کیپچر شق میں پہلا کردار ہونا چاہیے۔

جب سب پکڑے جاتے ہیں ، قیمت کے لحاظ سے ہوتے ہیں:

اگر پکڑے جانے والے تمام متغیرات کو قدر کے لحاظ سے پکڑا جائے ، تو صرف ایک = گرفتاری شق میں کافی ہوگا۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()
{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛ بولbl= سچ؛


آٹوfn= [=]()

{

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< '،' <<bl<< 'n'؛

}؛

fn()؛


واپسی ؛


}

پیداوار یہ ہے:

5 ، 2.3 ، A ، 1۔

نوٹ : = ابھی تک صرف پڑھنے کے لیے ہے۔

اگر کچھ متغیرات کو قدر اور دوسروں کو حوالہ کے ذریعے پکڑنا ہے ، تو ایک = صرف پڑھنے کے لیے نقل شدہ تمام متغیرات کی نمائندگی کرے گا ، اور باقی ہر ایک کے پاس ہوگا ، جیسا کہ مندرجہ ذیل پروگرام سے ظاہر ہوتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

intمرکزی()

{

intآئی ڈی= ؛ تیرنافٹ= 2.3۔؛ چارچودھری= 'سے'؛ بولbl= سچ؛


آٹوfn= [=،&چودھری،&bl]()

{

چودھری= 'بی'؛bl= جھوٹا؛

لاگت <<آئی ڈی<< '،' <<فٹ<< '،' <<چودھری<< '،' <<bl<< 'n'؛

}؛

fn()؛


واپسی ؛

}

پیداوار یہ ہے:

5 ، 2.3 ، بی ، 0۔

نوٹ کریں کہ = اکیلے کیپچر شق میں پہلا کردار ہونا ضروری ہے۔

لیمبڈا ایکسپریشن کے ساتھ کلاسیکل کال بیک فنکشن اسکیم۔

مندرجہ ذیل پروگرام سے پتہ چلتا ہے کہ لیمبڈا اظہار کے ساتھ کلاسیکی کال بیک فنکشن اسکیم کیسے کی جا سکتی ہے۔

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

چار *پیداوار؛


آٹوسی بی اے= [](چارباہر[])

{

پیداوار=باہر؛

}؛



باطلmainFunc(چاران پٹ[]،باطل (*کے لیے)(چار[]))

{

(*کے لیے)(ان پٹ)؛

لاگت<<'بنیادی کام کے لیے'<<'n'؛

}


باطلfn()

{

لاگت<<'ابھی'<<'n'؛

}


intمرکزی()

{

چاران پٹ[] = 'کال بیک فنکشن کے لیے'؛

mainFunc(ان پٹ ، سی بی اے۔)؛

fn()؛

لاگت<<پیداوار<<'n'؛



واپسی ؛

}

پیداوار یہ ہے:

پرنسپل فنکشن کے لیے

ابھی

کال بیک فنکشن کے لیے

یاد رکھیں کہ جب لیمبڈا ایکسپریشن کی تعریف عالمی دائرہ کار میں کسی متغیر کو تفویض کی جاتی ہے تو ، اس کا فنکشن باڈی کیپچر شق کو استعمال کیے بغیر عالمی متغیرات دیکھ سکتا ہے۔

پچھلی-واپسی کی قسم۔

لیمبڈا ایکسپریشن کی ریٹرن ٹائپ آٹو ہے ، یعنی کمپائلر ریٹرن ایکسپریشن سے واپسی کی قسم کا تعین کرتا ہے (اگر موجود ہو)۔ اگر پروگرامر واقعی واپسی کی قسم کی نشاندہی کرنا چاہتا ہے ، تو وہ اسے مندرجہ ذیل پروگرام کی طرح کرے گا:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

آٹوfn= [](intرک جاؤ) -> int

{

intجواب=رک جاؤ+ ؛

واپسیجواب؛

}؛


intمرکزی()

{

آٹومختلف=fn()؛

لاگت <<مختلف<< 'n'؛


واپسی ؛

}

آؤٹ پٹ 5 ہے۔ پیرامیٹر لسٹ کے بعد ، تیر والے آپریٹر کو ٹائپ کیا جاتا ہے۔ اس کے بعد واپسی کی قسم ہوتی ہے (اس معاملے میں int)۔

بندش

درج ذیل کوڈ کے حصے پر غور کریں:

ساختکلا۔

{

intآئی ڈی= ؛

چارچودھری= 'سے'؛

}obj1 ، obj2۔؛

یہاں ، کلا اسٹرکٹ کلاس کا نام ہے۔ Obj1 اور obj2 دو اشیاء ہیں جنہیں سٹرکٹ کلاس سے فوری طور پر نکالا جائے گا۔ نفاذ میں لیمبڈا اظہار اسی طرح ہے۔ لیمبڈا فنکشن کی تعریف ایک قسم کی کلاس ہے۔ جب لیمبڈا فنکشن کو کہا جاتا ہے (طلب) ، کسی شے کو اس کی تعریف سے فوری طور پر نکال دیا جاتا ہے۔ اس شے کو بندش کہتے ہیں۔ یہ وہ بندش ہے جو لامبڈا کے متوقع کام کو انجام دیتی ہے۔

تاہم ، اوپر کے ڈھانچے کی طرح لیمبڈا اظہار کو کوڈنگ کرنے سے obj1 اور obj2 متعلقہ پیرامیٹرز کے دلائل سے بدل جائیں گے۔ مندرجہ ذیل پروگرام اس کی وضاحت کرتا ہے:

#شامل کریں

استعمال کرتے ہوئے نام کی جگہگھنٹے؛

آٹوfn= [](intپیرام 1 ،intپیرام 2۔)

{

intجواب=پیرام 1۔+پیرام 2۔؛

واپسیجواب؛

} (،)؛


intمرکزی()

{

آٹوکہاں=fn؛

لاگت <<کہاں<< 'n'؛


واپسی ؛

}

آؤٹ پٹ 5 ہے۔ دلائل 2 اور 3 قوسین میں ہیں۔ نوٹ کریں کہ لیمبڈا ایکسپریشن فنکشن کال ، ایف این ، کوئی دلیل نہیں لیتا کیونکہ لیمبڈا فنکشن ڈیفینیشن کے اختتام پر دلائل پہلے ہی کوڈ ہو چکے ہیں۔

نتیجہ

لیمبڈا اظہار ایک گمنام فعل ہے۔ یہ دو حصوں میں ہے: کلاس اور آبجیکٹ۔ اس کی تعریف ایک قسم کی کلاس ہے۔ جب اظہار کہا جاتا ہے ، تعریف سے ایک شے بنتی ہے۔ اس شے کو بندش کہتے ہیں۔ یہ وہ بندش ہے جو لامبڈا کے متوقع کام کو انجام دیتی ہے۔

بیرونی فنکشن کے دائرے سے متغیر حاصل کرنے کے لیے لیمبڈا ایکسپریشن کے لیے ، اسے اپنے فنکشن باڈی میں غیر خالی کیپچر شق کی ضرورت ہوتی ہے۔