Coroutine (توقف و ادامه ی اجرای کد در لوا) :
اول باید تشکر کنم از اوستا اشکان و اوستا محمد که تو ارائه این بحث کمک کردن (ممنان گلپسران) برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
این کار رو با کمپوننت اتوات هم میشه انجام داد ولی راه اجرای مستقیمش تو لوا همینه
درباره اش که دیگه توضیح نمیخاد . ها؟ کارش اینه که تو کوروتین ای که تعریف کردیم ، میتونیم هر وقت دلمون خاست ، اجرای کد رو متوقف کنیم و هر وقت دلمون خاست ، ادامه کد رو اجرا کنیم . حالا مستقیم میریم سر اصل Matlab برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید (جان من الان ساعت دقیق 2:45 دیقه هه . ببینین ساعت چن این کتاب تموم میشه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) . اول دونه دونه ی توابع کورتین توضیح داده میشه بد میریم سر وقت مثالا . فقط اوایلش شاید یه کم گیج کننده باشه پس خوب بگوشین برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید . میتونین توضیح رو از اینجا هم ببینین :
Lua 5.1 Reference Manual
coroutine.create : برای تعریف کوروتین تا اینکه تابعی رو تو وسطش یا هرجای دیگه اش متوقف کنیم ، اول باید کوروتین رو ایجاد کنیم با همین تابع . به عنوان ورودیش ، اون تابعی که میخایم کد وسطش توقف پیدا کنه رو میدیم . کار اصلی این تابع اینه که به تابع coroutine.resume که توضیح داده میشه درباره اش ، میگه که آخرین باری که کد توقف پیدا کرد ، تو کدوم خط بود. یادتون باشه ، بعد از تعریف یا فراخونی این تابع coroutine.create ، دیگه تابع coroutine.resume نمیدونه از کجا شروع کرده بود و کدها رو از اول اجرا میکنه ینی اگه هر وقت از این تابع coroutine.create استفاده کنیم ، بعد از اون ، اولین باری که از تابع coroutine.resume استفاده میکنیم (اولین بارها نه اینکه چندین بار) ، تابعی که تو ورودی coroutine.create داده بودیم تا کدها رو متوقف کنیم هر وقت دلمون خاست ، این تابع از اول کداش اجرا میشه
تابع coroutine.create هم مقداری از نوع نخ یا thread رو برمیگردونه . که من نفمیدم این دقیقا چیه اما مقدار بازگشتیش اصلا برامون مهم نیست ولی هر چی که هست ، این قدو میدونیم حاوی اطلاعات این هست که آخرین بار تا کجا کدمون اجرا شده بود و برا تابع coroutine.resume میفرسته این اطلاعاتو تا بفمه از کجا باید ادامه بده . اما همونطور که گفته شد ، این تیکه آخر برا اطلاعات عمومی هه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
coroutine.resume : از وقتی که تابع coroutine.create تعریف شد تا زمانی که اون تابع مورد نظرمون که به عنوان ورودی تو coroutine.create دادیم ،تموم نشد ، این تابع coroutine.resume هر وقت که اجرا بشه ، ادامه ی کدهای اون تابع رو اجرا میکنه منتها چندین نکته ی اساسی مهم داره :
اول اینکه اگه تابع برا ایجاد کوروتین قبل استفاده از هر تابعی از توابع این خانواده من جمله coroutine.resume یا coroutine.yield تعریف نشده باشه و یا به عبارتی تابع coroutine.resume یا coroutine.yield ، اول از همه تعریف شده باشن ، ارور میده برنامه
دوم اینکه زمانی که اون تابع مورد نظرمون که به عنوان ورودی تو coroutine.create دادیم ،تموم بشه ، دیگه تابع coroutine.resume نمیتونه کدها یا همون تابع ی که تو کوروتین دادیم رو دوباره اجرا کنه (ینی فقط یه بار اجرا میشه) و اگه بخایم دوباره اجرا کنه ، باید قبل از coroutine.resume ، دوباره همون تابع coroutine.create رو فراخونی کنیم تا دوباره ساخته شه
سوم و مهم ترین نکته اینکه بعد از هر بار فراخونی یا ایجاد کوروتین با تایع coroutine.create ، اولین بار بود که coroutine.resume رو فراخونی کردیم ، در این صورت ورودی های اولین تابع coroutine.resume که فراخونی شد (در مثال لینک بالا Val1) (تا وقتی که تابع مورد نظرمون تمام نشد یا coroutine.create دوباره فراخونی نشد) همون برابر ورودی های توابع مورد نظرمون استفاده میشن . اما از اون به بعد ینی تو فراخونیهای بعدی تابع coroutine.resume (تا وقتی که تابع مورد نظرمون تمام نشد یا coroutine.create دوباره فراخونی نشد) ، ورودی های coroutine.resume (در صورت وارد کردن ورودی . در مثال لینک بالا همون Val1) به عنوان خروجی یا همون مقدار (سمت چپ مساوی) تابع بعدی coroutine.yield ذخیره میشه . مقدار بازگشتی خود coroutine.resume هم بولین (true در صورتی که کدها تموم نشده باشه تو تابع موردنظر و یا ارور نداده باشه وگرنه false هست) به اضافه ی یه مقدار دیگه (ینی تابعی هست که چندین مقدار رو برمیگردونه مثل مثال پست بالا) که اگه false باشه ، متن ارور رو میده (در صورتی که تموم شده باشن کدها و کاملا اجرا شده باشن ، متن cannot resume dead coroutine رو برمیگردونه) و اگه true باشه ، ورودی های تابع coroutine.yield به عنوان متغییرهای تابع coroutine.resume (سمت چپ مساوی این تابع) ذخیره میشن و خوب ملومه که تعدادشونم به تعداد ورودی های تابع coroutine.yield وابسته هست
در کل ینی در واقع بصورت ضربدری میشه رابطه ی بین دو تابع coroutine.resume و coroutine.yield . در صورت داشتن ورودی ، ورودی تابع coroutine.yield به عنوان خروجی coroutine.resume ذخیره میشه و ورودی تابع coroutine.resume (البته با شرایطی که تو بالا گفته شد ینی اولین تابعش نه که به عنوان ورودی های توابع اصلی در نظر گرفته میشه تا آخرین لحظه ای که کدها تموم شن یا کوروتین جدید تشکیل شه) هم به عنوان خروجی coroutine.yield ذخیره میشه
نکته ی چهارمم اینکه پس ورودی و خروجی این دو تا تابع باید با هم برابر باشن. ینی ورودی تابع coroutine.yield با خروجی تابع coroutine.resume و همینطور ورودی تابع coroutine.resume با خروجی تابع coroutine.yield بصورت دو به دو یا ضربدری با هم برابر باشند . اگه این طور نباشه یا در کل هر حالتی پیش بیاد (مثلا نوع متغییرمون اشتباه باشه به عنوان ورودی برا تابع اصلی کوروتین) که در صورت عادی باعث بوجود اومدن ارور بشه ، این حالت تو کوروتین ها بجا ارور ندادن ، اصلا اون قسمت یا کل تابع کوروتین (منظورم همون تابع اصلی مورد نظرمون هست) اصلا اجرا نمیشه (که ارور بده یا نده) پس حواستون رو به سمت دقت جمع کنین برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
توضیح مقدار ورودی اش هم که سایت بالا اینجوری گزاشت :
اولا هر جا تو برنامه نویسی علامت پرانتز یا opt که مخفف optional هست یا علامت سه تا نقطه ... ینی دلخواهی که خاستین پر کنین یا نکنین اما تو اینجا اولین آرگومان یا ورودی اش که co هست منظورش اینه که تابع کوروتین رو که قبلا ایجاد شده بود با coroutine.create رو هدف قرار بده برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید (تو تابع یا در واقع کوروتین co) ینی تو این تابع که اسمش co هست . تو ورودی بعدی coroutine.resume که دلخواهی بود ، همونطور که گفته شد ، برا بار اول که coroutine.resume فراخونی شد ، این قسمت پارامترش که تو مثال بالا گفت دلخواهی هست ، همون به عنوان پارامترهای ورودی تابع کوروتین یا اصلی ما استفاده میشه اما در دفعات بعدی (تا تموم شدن یا فراخونی یا ایجاد تابع کوروتین یا coroutine.create) که تابع coroutine.resume تکرار بشه ، همین پارامتر که ورودی اش به عنوان خروجی تابع coroutine.yield استفاده میشه ، بسته به نکته ی چهارم تو بالا (بسته به تعداد متغییر یا خروجی تابع coroutine.yield بعدی) ، میتونیم این بار ورودی coroutine.resume رو هر چی که دلمون خاست بدیمکد:coroutine.resume (co [, val1, ···])
شاید مثل من قاتی کرده باشین مطالب رو برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید اما این مطالب رو یادتون فقط باشه تو مثال قشنگ متوجه میشین
coroutine.running : تست نکردمبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
coroutine.status : مقدار رشته ای رو برمیگردونه. اگه کوروتین با تابع coroutine.yield متوقف بشه ، رشته ی "suspended" و اگه ارور بده و یا تموم شده باشه کوروتین ما (تابع اصلی مون تا خط آخر اجرا شده باشه) ، رشته "dead" رو برمیگردونه
به عنوان ورودی شم اسم کوروتین (اسم تابع coroutine.create) رو میزاریم که وضعیت اون کوروتین رو مشخص کنه . رشته "running" هم موقع اجرای تابع برگردونده میشه و رشته ی "normal" هم دقیق نمیدونم .
coroutine.wrap : که دقیق کار همون تابع coroutine.creat رو میکنه اما انگار مقدار بازگشتیش ، همون مقدار تابع coroutine.resume هست بدون مقدار بولین اش . گفتم انگار چون با این تابع کار نکردم اما بازم انگار برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید آسون تر از اولی باشه . بازم نمیدونم
coroutine.yield : اون کوروتینی (تابع اصلی مون) که توش این تابع coroutine.yield بکار رفته شه ، اول این تابع اجرا میشه و از خط بعدیش دیگه اجرا نمیشه تا وقتی که دوباره تابع coroutine.resume فراخونی بشه . درباره آرگومان هاش و خروجی هاش هم که تو قسمت coroutine.resume توضیح داده شد . حتما بهش سر بزنین تا از ورودی و خروجیش مطلع بشین
آخیش . تازه رسیدیم سر مثال اول :برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
مثال ها هم از این سایت زیر گرفته شد (سایت خیلی خوبی هه ها برا کلیه ی زبان ها آموزش داره) :
Lua - Coroutines
خوب بتوجهین گلپسران . تو گلوبال فانکشن این کد رو بزارین: برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
تو یه رویداد دیگه که میخاین کد اجرا بشه ، این کد رو بزارین :کد:function f(value1,value2) tempvar3 =10; Dialog.Message("Notice", "coroutine section 1\n".."value1 = "..value1 .."\nvalue2 = "..value2 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); tempvar1 = coroutine.yield(value1+1,value2+1); tempvar3 = tempvar3 + value1; Dialog.Message("Notice", "coroutine section 2\n".."tempvar1 = "..tempvar1 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2); tempvar3 = tempvar3 + value1; Dialog.Message("Notice", "coroutine section 3\n".."tempvar1 = "..tempvar1 .."\ntempvar2 = "..tempvar2 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); return value2, "end" end
اول بگم که این کد بالا رو میتونین این جوری هم بنویسین :کد:co = coroutine.create(f) Res1,A1,A2 = coroutine.resume(co, 3, 2) if Res1==true then Dialog.Message("Notice", "main\n"..A1 .."\n"..A2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res2,B1,B2 = coroutine.resume(co, 12,14) if Res2==true then Dialog.Message("Notice", "main\n"..B1 .."\n"..B2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res3,C1,C2 = coroutine.resume(co, 5,6) if Res3==true then Dialog.Message("Notice", "main\n"..C1 .."\n"..C2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res4,D1 = coroutine.resume(co, 10,20) if Res4==false then Dialog.Message("Notice", "main\n"..D1 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end
کد:co = coroutine.create(function (value1,value2) tempvar3 =10; Dialog.Message("Notice", "coroutine section 1\n".."value1 = "..value1 .."\nvalue2 = "..value2 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); tempvar1 = coroutine.yield(value1+1,value2+1); tempvar3 = tempvar3 + value1; Dialog.Message("Notice", "coroutine section 2\n".."tempvar1 = "..tempvar1 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2); tempvar3 = tempvar3 + value1; Dialog.Message("Notice", "coroutine section 3\n".."tempvar1 = "..tempvar1 .."\ntempvar2 = "..tempvar2 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); return value2, "end" end ) Res1,A1,A2 = coroutine.resume(co, 3, 2) if Res1==true then Dialog.Message("Notice", "main\n"..A1 .."\n"..A2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res2,B1,B2 = coroutine.resume(co, 12,14) if Res2==true then Dialog.Message("Notice", "main\n"..B1 .."\n"..B2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res3,C1,C2 = coroutine.resume(co, 5,6) if Res3==true then Dialog.Message("Notice", "main\n"..C1 .."\n"..C2 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Res4,D1 = coroutine.resume(co, 10,20) if Res4==false then Dialog.Message("Notice", "main\n"..D1 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end
اولا فرق شون تو اسم تابع هست که اولی اسمش f و تو دومی اسم نداره . دوما فرق شون اینه که تو کد اول که جدا هستن ، اگه تابع رو جداگانه خودمون فراخونی کنیم (بدون کوروتین منظورمه ها) تا اونجایی که ربطی و تابعی از کوروتین (coroutine.yield) نداره ، سالم اجرا میشه قبلش و بهش که رسید ارور میده اما تو کد دوم کلا اجرا نمیشه (احتمالا تو روش دوم همون قضیه ی پست بالا باشه که گفته شد (تابع در تابع))
برا اینکه شماره گزاری راحت تر شه ، دومین کد رو میگم:
خط اول که بسم ا... کوروتین ینی ساخت کوروتین هه که ورودی شم تابع مورد نظر مونو میزاریم توش (توضیح کاملش بالا داده شده) . اسمشم co گزاشتیم. پس این co کوروتینی هست که حاوی تابع اصلی مونه
حالا یهو پرش میکنیم روی خط چارده (بخاطر این اف چهارده آواتارمبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) چون تابع که خودش به خودی خود اجرا نمیشه و با فراخونی اجرا میشه که بده تابع ینی تو خط 14 فراخونی شد :
این تابع که میدونین برا اجرا یا ادامه ی اجرای تابع داخل کوروتین هست . از ورودی شروع میکنیم ینی فعلا به متغییر یا خروجی این تابع کاری نداریم . ورودی اش همونطور که گفته شد ، اولین پارامترشو اسم کوروتین مونو برا اجرای کدای توابعش میزاریم که co بود . پارامتر بدی که با ویرگول ازش جدا میشه ، این جوری تعیین میشه که اول میگیم آیا این تابع coroutine.resume ، اولین اجرا بعد از آخرین اجرای تابع coroutine.create هست؟ یعنی coroutine.create که فراخونی شد ، بعد از اون ، اولین باره که تابع coroutine.resume فراخونی شد؟کد:Res1,A1,A2 = coroutine.resume(co, 3, 2)
آری دیگر . ها؟ خوب پس اگه اولین باره ، پارامترهای بعدی این تابع coroutine.resume (که تو اینجا 3 و 2 هه) همون به عنوان ورودی یا آرگومان تابع اصلی مون (تابعی که تو ورودی coroutine.create گزاشتیم) هست و تا آخر هم هر چند بار که تابع coroutine.resume اجرا شه اما ورودی تابع اصلی مون همین مقدار اولین باری که تو تابع coroutine.resume بود ، ثابت میمونه و تغییر نمیکنه (البته تا زمانی که کدهای تابع اصلی مون تموم نشه که در این صورت اصلا تابع coroutine.resume کار نمیکنه و یا اینکه دوباره تابع coroutine.create اجرا نشه که در این صورت ، باز اولین تابع coroutine.resume ای که بعد از coroutine.create اجرا شه ، به عنوان ورودی اصلی تابع اصلی مون در نظر گرفته میشه)
اگه بازم پیچیده شد این تیکه ، نگران نباشین ، پلین در خدمت تان اسب برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ادامه رو گوش کنین متوجه میشین
پس تا حالا چی شد؟ کوروتین تو خط اول تشکیل شد و اسمشم شد co و تو خط 14 ام ، با تابع coroutine.resume گفت که کدهای کوروتین co با متغییر اولش که 3 هست (ینی Value1 تو تابع اصلی مون برابر 3 میشه) و متغییر دومش (ینی Value2=2 میشه) اجرا بشه
درباره خروجی این تابع تو خط چهارده بعدا صوبت میکنیم . چرا؟ چون بصورت ضربدری بود قضیه دیگه
پس الان دستور اجرای کد رسیده و کوروتین اجرا میشه . خط دوم که هیچ چی . میرسیم خط سوم که :
خروجیش که ملومه Value1 که 3 بود و Value2 که 2 بود و Value3 هم که تو خط دوم 10 بودکد:Dialog.Message("Notice", "coroutine section 1\n".."value1 = "..value1 .."\nvalue2 = "..value2 .."\ntempvar3 = "..tempvar3 , MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
تو خط چهارم ، اول این خطه اجرا میشه و بعد از اون دیگه متوقف میشه . تابع coroutine.create هم که تا این خط رو برا نشونه به تابع coroutine.resume بعدی (این تو خط چهارده نه ها ، خط 19 منظورمه) میفرسته که از اون خط به بعد اجرا شه :
پارامترهاش هم که ملومه دیگه . اولین پارامترش 4 و دومین اش میشه 3 . قبلا چجوری گفته شد؟ بصورت ضربدری هستش رابطه شون دیگه . ها؟ ینی پارامترهای تابع coroutine.yield تو متغییر یا خروجی coroutine.resume ذخیره میشن و برعکس. بازم خروجی یا متغییر اینو بعدا حساب میکنیم که چی درمیاد . فعلا این خط تمام شد و کوروتین co کداش متوقف شد و میریم تو خط چهاردهم که بودیم . تو اینجا 3 تا متغییر داریم که به ترتیب Res1 و A1 و A2 هه . گفته شد که تابع coroutine.resume دو نوع متغییر رو ذخیره میکنه که اولیش بولین هه و اگه تابع اصلی مون تموم نشده باشه ، true وگرنه false رو برمیگردونه . پس تابع اصلی یا کوروتین مون که کداش تموم نشد (مکث کردن منظورم نیست ها) پس تو Res1 مقدار true ذخیره میشه. بقیه ی مقادیرها هم که گفته شد همون ورودی تابع coroutine.yield که به ترتیب اولی 4 و دومی 3 بود ، توی خروجی یا متغییرهای بعدی تابع coroutine.resume به ترتیب ذخیره میشن ینی مقدار A1 میشه برابر با اولین مقدار پارامتر coroutine.yield که 4 بود و دومی هم به همین ترتیب میشه A2 برابر 3کد:tempvar1 = coroutine.yield(value1+1,value2+1);
خوب همونطور که قبلا هم گفته شد ، پارامترهای ورودی تابع coroutine.yield کاملا دلخواهی هست که مقدارشو چی بزاریم و اصلا ربطی به هیچ الگوریتم و مقادیر دیگه ای نداره اما اینکه کلا بزاریم یا چن تا بزاریم ، برمیگرده به خروجی تابع coroutine.resume (که الان دیدین) ینی الان تو مثال بالا اگه میخاین به تابع coroutine.yield تو خط چهارم مقدار ندین (البته اگه مقدار نمیدین ، علامت پرانتز رو به عنوان تابع پاک نکنین) باید تو خط چهاردهم ، متغییرهای A1 و A2 رو برای coroutine.resume ست نکنین
نکته ای که اینجاست اینه که درسته پارامتر و آرگومان های coroutine.yield دلخواهی هه اما چون تابع اصلی مون وسط کار متوقف میشه ، این قابلیت هست که بجای مقدار بازگشتی اون تابع ، از این آرگومان و ورودی این تابع بجاش استفاده کرد
بعد تو خط 15 که شرط برقراره و تو خط 16 هم که مقادیرها نشون داده میشن که تازه توضیح داده شد
حالا خط 19 اجرا میشه :
مثل قبلی هه کلا اول با خروجی یا متغییرهاش کاری نداریم . مستقیم سر وقت ورودی. قبلشم خوب ملومه دیگه میگه کوروتین co رو کداشو ادامه بده . قبلشم تابع coroutine.create ، ملوم کرد براش که از کجا شروع کنه که همون خط زیر آخرین تابع coroutine.yield ای بود که اجرا شده بود ینی از خط 5 ام شروع به اجرا شدن میکنه منتها اول ورودی تابع coroutine.resume باید تو خط 19 (خط بالا) ملوم شه که چی کاره ان؟ همه کاره ان برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید برا تعیین این ورودی چه سئوالی از خودمان میپرسیدیم گلپسران؟ تکرار کنم عایا؟ برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید آیا این تابع coroutine.resume ، اولین اجرا بعد از آخرین اجرای تابع coroutine.create هست؟ یعنی coroutine.create که فراخونی شد ، بعد از اون ، اولین باره که تابع coroutine.resume فراخونی شد؟ آیا ازدواج با مرد عنکبوتی کار خوبی ست ؟ برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنیدکد:Res2,B1,B2 = coroutine.resume(co, 12,14)
جواب خیر است دیگر بالام جان ها دیگر . ها؟ این الان دومین باره که اجرا شد تابع coroutine.resume بعد از آخرین اجرای تابع coroutine.create که تو خط اول بود . یه بار coroutine.resume تو خط چهارده و الان دومین بار تو خط 19 اجرا شد
جواب اگه منفی هه ، در این صورت ، ورودی های تابع coroutine.resume به عنوان خروجی یا متغییر تابع coroutine.yield قبلی (در اینجا قبلی اش تو خط 4 هه دیگه) استفاده میشه . اگه مثبت بود که مثل بالا ، ورودی هاش به عنوان ورودی تابع اصلی یا کوروتین مون استفاده میشه.
پس الان ورودی توابع مون یعنی Value1 و Value2 هم همون قبلی ان دیگه یعنی به ترتیب 3 و 2
خوب الان تو خط 19 ، ینی تو تابع coroutine.resume ، اولین ورودیش 12 و دومیش 14 هه . گفته شد این ورودی ها تو متغییر یا به عنوان مقدار بازگشتی تابعcoroutine.yield قبلی (که تو خط 4 آخریش بود) ذخیره و بازگردونده میشه . خط 4 هم یه متغییر داره فقط . اسمشم tempvar1 هست . پس ملومه که فقط جای اولین متغییر رو داره ینی تو tempvar1 فقط عدد 12 برگردونده یا ذخیره میشه . اگه این تابع دو متغییر داشت ، تو دومیش 14 هم ذخیره میشد
حالا ادامه ی خط هاش اجرا میشه
تو خط 5 ، مقدار Value1 که 3 بود و مقدار tempvar3 هم که 10 بود که جمعش میشه 13 و تو tempvar3 ذخیره میشه
تو خط 6 هم که مقدار این دو تا رو فراخونی کرد که اشاره شد
تو خط 7 ام ، مثل قبلا ، اول coroutine.yield اجرا میشه و ورودی هاش تو خروجی تابع coroutine.resume ای که باعث اجراش شده بود ینی تابع خط 19 ذخیره میشه . مقادیر ورودیهاش که ملومه . تو خط 7 ام ، اولین آرگومان ورودیش میشه 5 و دومیشم 1 دیگه (Value1=3 و Value2=2 بود دیگه)
دوباره میرسیم به خط 19 . مثل قبلی Res2 مقدارش true میشه و B1 برابر اولین آرگومان آخرین تابع coroutine.yield (که تو خط 7 اجرا شده بود) میشه و ... ینی B1 برابر 5 و B2 برابر 1 میشه
دیگه خط 20 و 21 که ملومه
حالا خط 24 اجرا میشه . اون سئوالم از خودتون بپرسین ، جوابش میشه خیر برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید پس پارامتر اول تابع coroutine.resume تو این خط ، تو اولین متغییر coroutine.yield تو خط 7 ام ذخیره میشه و دومی آرگومان هم همینطور هم همینطور پس مقدار متغییر tempvar1 تو خط 7 ام میشه 5 و tempvar2 میشه 6
تو خط هشتم ، آخرین بار tempvar3 برابر 13 بود . Value1 هم که تغغیری نکرد و 3 هست که جمع میشن و 16 تو tempvar3 ذخیره میشه
خط نهم هم که ملومه . تابع دو مقدار رو برمیگردونه که Value2 برابر 2 بود و یکی دیگه هم که رشته ی "end" هه
حالا دوباره میره رو خط 24 . درسته که علی الظاهر تابع اصلی مون به آخر رسید اما این بار ، مقدار true رو باز برمیگردونه (دفعات بعد مقدار false رو برمیگردونه) چون این بار تابع coroutine.resume خط 24 تونست کدهای کوروتین رو اجرا کنه . پس تو متغییر Res3 مقدار true ذخیره میشه. حالا که تابع تموم شد ، بجای ورودی تابع coroutine.yield ، مقدار بازگشتی تابع اصلی مون که Vlue2 و "end" هستش به ترتیب تو متغییر coroutine.resume خط 24 ذخیره میشه پس C1 میشه 2 و C2 میشه "end"
حالا خط 29 اجرا میشه :
اجرا میشه و مقدار بازگشتیش چیه؟ چون کامل کوروتین اجرا شد ، اولین مقدار ینی Res4 برابر false میشه و متغییر D1 هم توش متن ارور که موقه تموم شدن این پیام میده ، ذخیره میشه : "cannot resume dead coroutine"کد:coroutine.resume(co, 10,20)
خروجی کلی این مثال میشه :
خسته که نشدین؟ زیاده؟ تهش به اندازه یه کتابه دیگه . به جون شما ، مِردال شدم رفت . اون موقه کی بد ، الان کی هه . ساعت 10 و ربهبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنیدکد:coroutine section 1 3 2 10 main 4 3 coroutine section 2 12 13 main 5 1 coroutine section 3 5 6 16 main 2 "end" main "cannot resume dead coroutine"
مثال دوم (تکرار با استفاده از کوروتین) :
به جون شما این آخرین مثاله .برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
میرویم به خط 27 چون بقیه تابع ان تا فراخونی نشن ، اجرا نمیشنکد:function getNumber() local function getNumberHelper() co = coroutine.create(function () coroutine.yield(1) coroutine.yield(2) coroutine.yield(3) coroutine.yield(4) coroutine.yield(5) end) return co end if(numberHelper) then status, number = coroutine.resume(numberHelper); if coroutine.status(numberHelper) == "dead" then numberHelper = getNumberHelper() status, number = coroutine.resume(numberHelper); end return number else numberHelper = getNumberHelper() status, number = coroutine.resume(numberHelper); return number end end for index = 1, 10 do Dialog.Message("Main", index.."\n"..getNumber(), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end
index که شمارنده هه . 10 بار تابع getNumber() همراش فراخونی میشه . که هر 10 بار رو چک میکنیم (3 بارشو چک میکنیم ، بقیه که ملوم میشه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید )
لازم به ذکر است (اخبار نیستا برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) که طبق مثال پست بالا ، تو خط 27 چون تابع getNumber() تو تابع Dialog.Message فراخونی شد ، اول تابع getNumber() اجرا میشه و بعد اگه مقدار بازگشتی داشت ، تو تابع Dialog.Message ذخیره میشه
بار اول :
بازم لازم به ذکر است (بازم اخبار نیستابرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) که طبق مثال پست بالا ، چون تابع getNumberHelper داخل تابع getNumber هست پس تا از داخل تابع getNumber ، تابع getNumberHelper فراخونی نشه ، تابع getNumberHelper اجرا نمیشه . پس بازم میرسیم مستقیم به خط 12 اون شرطه . میدونین که یه متغییر خالی تو شرط بیاد (تو خ 12منظورمه که متغییر numberHelper هه) ینی اینکه اون متغییر مقدار داشته باشه یا مخالف nil باشه ، شرط اجرا میشه . بار اول هم چون این متغییر numberHelper پوچ یا nil هست ، پس قسمت else اجرا میشه ینی خط 20 ام
تو خط 20 ام ، تابع getNumberHelper() فراخونی شد و تو متغییر numberHelper ذخیره شد . معنی اش دیگه ملومه ینی هر وقت numberHelper اسمش برده شد ، ینی اسم getNumberHelper() برده شد و این تابع رو اجرا کنه
پس با این اوضاع ، میره به خط دوم و تابع getNumberHelper() رو اجرا میکنه . و خط سوم هم کوروتین رو با اون تابعی که بهش داده شده ایجاد میکنه بازم با نام co اما کوروتین اجرا نمیشه ها . یادمون باشه که کوروتین فقط با دستور تابع coroutine.resume اجرا میشه . سر آخر هم تو خط 10 ، تابع getNumberHelper() خود کوروتین co رو برمیگردونه . خوب توی متغییرها هم که اگه تابع سمت راست ، مقدار بازگشتی داشت که تو سمت چپ یا همون متغییرش اون مقدار ذخیره میشه اما اگه مقدار بازگشتی نداشت (البته جدای از قضیه ی thread که برمیگردونه) ، وقتی اون متغییر رو فراخونی کنیم ، انگار خود اون تابع رو اجرا کردیم. از اون طرف هم متغییر numberHelper تابع getNumberHelper() و خود تابع getNumberHelper() کوروتین co رو برمیگردونه پس در واقع متغییر numberHelper کوروتین co رو برمیگردونه ینی در واقع اندر واقع هر وقت متغییر numberHelper رو فراخونی کردیم منظورمون همون کوروتین co هست .
خوب پس تا اینجا این شد که تو خط 20 ، چون getNumberHelper() فراخونی شد و ادامه ی قضیه های پشت سرش که گفته شد ، باعث ایجاد کوروتین شد
حالا خط 21 :
مثل قضیه ی بالا ، اول ، متغییرهاشو میزاریم کنار و بعدا حساب میکنیم . اول به آرگومان های ورودیش میرسیم که نداره برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید میگه تو کوروتین numberHelper که گفته شد همون کوروتین co (تو خط سوم) هست ، رو اجرا کنه (چون اولین اجراشه بعد از ایجاد آخرین کوروتین) و آرگومان هم که نداره ینی این معنی رو میده که تابع coroutine.yield مربوط بهش ، خروجی یا متغییر برا ذخیره شدن نداره .کد:status, number = coroutine.resume(numberHelper);
پس تابع کوروتین ینی خط چهارم اجرا میشه. همینجا خِرشو میگیره و کد متوقف میشه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید و ورودی coroutine.yield تو خط 4 ام که 1 هست مثل قبلی ، تو خروجی یا متغییر آخرین تابع coroutine.resume که تو اینجا تو خط 21 بود ذخیره میشه منتها قبلش تو اولین متغییرش مقدار بولین که true هست ذخیره میشه پس متغییر status مقدارش true و متغییر number مقدارش 1 میشه . تو خط 21 هم که کلمه return اومد که مال تابع getNumber() هست ینی این تابع ، مقدار number که 1 هست رو برمیگردونه. و بعد تو خط 27 مینویسه . حالا حلقه for برا دومین بار تکرار میشه و دوباره تابع getNumber() رو فراخونی میکنه . دوباره هم توابع داخلی یا getNumberHelper() اجرا نمیشه چون فراخونی نشد و مستقیم سر خط 12 میره و شرط رو چک میکنه که این بار این شرط برقراره ینی متغییر numberHelper مقدارش مخالف nil هست که مقدارش همون تابع رو تو خودش ذخیره میکنه پس مستقیم به خط 13 میره :
میگه کوروتین co اجرا بشه ادامه اش . پس خط 5 اجرا و متوقف میشه بعدش . بازم status که true هست و number هم که 2 میشه (دیگه چندین بار توضیح داده شدبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید خسته شدم . نشدم . دشمن شدبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) حالا میره خط 14 و وضعیت این کوروتین رو میبینه تموم شد یا نه (dead هست یا نه) . اگه تموم شده باشه ، میگه کوروتین رو دوباره ایجاد کن که تو خط 15 میتونین ببینین که نوشته numberHelper = ()getNumberHelper که همونطور که تو خط بالاتر توضیح داده شد ، ینی فراخونی کوروتین و ینی ایجاد کورتین co جدید (اگه کوروتین تموم شده باشه اجرای توابعش ، دیگه تابع coroutine.resume نمیتونه اجراش کنه جز اینکه دوباره کوروتین فراخونی یا ایجاد شه)کد:status, number = coroutine.resume(numberHelper);
یادمون باشه اگه کوروتین رو قبل تمام شدن تابع کوروتین ، دوباره ایجاد کنیم ، تمام اطلاعات ریست میشه و تابع coroutine.resume ای که بعد از این فراخونی بشه ، این تابع کوروتین رو از اول اجرا میکنه و همینطور آرگومان هاش هم به عنوان آرگومان های کوروتین در نظر گرفته میشه چون اولین اجرای تابع coroutine.resume بعد از ایجاد کوروتین جدید هست که اینا قبلا گفته شد
به هر حال اینجا تو خط 14 هنوز شرط برقرار نیست چون اجرای کوروتین تموم نشد پس میره به خط 18 که return number هست که ینی تابع getNumber() مقدار number که الان 2 هست رو برمیگردونه و تو خط 27 چاپ میکنه
حالا تابع for سومین بار اجرا میشه و تا 5 امین بار همین حالت دوم که تو بالا گفته شد اجرا میشه
دفعه ی پنجم فرقش اینه که این بار چون شرط اتمام اجرای تابع یا "dead" برقرار میشه ، همون اولش تو خط 15 :
مثل بار اول تابع کوروتین دوباره اجرا میشه که باعث میشه تابع coroutine.resume کدهای کوروتین رو دوباره اجرا کنهکد:numberHelper = getNumberHelper()
گلپسران اگه اشکالی چیزی دیدین ، خوشحال میشم راهنمایی کنین
موفق و پیروز و سربلند باشین . مِرِه خو بَیته برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید






پاسخ با نقل قول

Bookmarks