M3RS4D 50062 (02-04-15), nima_hl (05-08-14)
یه نکته ی مهم و اشتباه برانگیز برای کد دادن به رویداد (رویداد اشیاء) :
اول از همه بگم این تیکه رو مدیون اوستا محسن ام و واقعا ازش ممنونم (ما را از هچل نجات داد )
نگا کنین ، به قول اوستا محسن ، یه پن شیش تا شی Button بزارین تو صفه با نام پیش فرض خودش و یه شی دیگه (مثلا Lable) هم بزارین . تو این لیبل هه ، این کد رو بدین :
کد:Page.SetObjectScript("Button"..j, "On Click", "Dialog.Message(\"\", j);"); j=j+1
تو گلوبال فانکشن یا استارت آپ هم این رو :
الان تصورتون چیه؟ دکمه ی 1 و 2 و 3 رو بزنین ، برا هر کدوم چه پیامی میده؟کد:j=1
تصور اغلب افرادی که مثل من ان اینه که وقتی دکمه ی Button1 رو بزنن ، پیام 1 رو میده (چون j در اون لحظه ، 1 هه) و وقتی دکمه ی دوم رو میزنین ، پیام 2 و ... رو بده
اما این گونه نیست چگونه هست؟
این جوریه که j مقدار اولیه اش تو دهلیز (نه بطن ) ورود ، 1 بود . بعد خط اول بالا که گفت تو Button..j ، کدی رو ست کن که مقدار j رو بنویسه. ینی چی تا اینجا؟ خوب مقدار j رو جایگزین کنین دیگه ینی اینکه تو Button1 ، پیام ای رو ست کن که عنوان اش ، 1 باشه (البته تا اینجا) . بعد تو خط بعد ، یکی به مقدار j میافزایه خوب حالا دوباره کد بالا رو ترجمه کنین با این مقدار جدید . چی میشه؟ تا اینجاش که رو Button1 ست کنه که انجام شد . هیچ چی . ینی نه اینکه مقدار j برابر 2 شد و از اون طرف هم گفتیم کد رو تو Button..j ست کن ، پس تو Button2 ست میکنه . این که ملومه اون خط کد اجرا شد و برای Button1 کد رو ست کرد و رف پی کارش . وقتی برا دکمه ی 2 ست میکنه کد رو که شما دوباره رو شی Lable کلیک کنین یا اینکه مثلا بعد خط دوم ، کد ست کردن رو مینوشتین. پس تا اینجا مشکلی ندارین؟ خوب حالا ادامه ی نگا رو میندازیم . پس تا اینجا j برابر 2 شد و تو دکمه ی اول یا Button1 این کد رو ست میکنه که وقتی کلیک کنیم ، مقدار j رو نشون میده که برابر چی هست؟ برابر 2
پس اولین باری که کلیک کنین تو دکمه ی اول ، پیام 2 رو میده نه 1 رو . چون قبل اجرا شدن دومین بار کد
کد:Page.SetObjectScript("Button"..j, "On Click", "Dialog.Message(\"\", j);");
، مقدار j یکی اضافه شد . حالا دومین بار وقتی کلیک کنین چی میشه؟ تو Button2 (چون j فعلا 2 هه) ، میگه j رو نمایش بده که قبل از اینکه کد خط بالا اجرا بشه ، مقدار j یکی اضافه میشه پس وقتی دکمه ی 1 یا 2 رو کلیک کنین که دستور داده شد مقدار j رو نشون بده تو هر دوشون ، هر کدوم رو کلیک کنین ، مقدار 3 پیام داده میشه و الی آخر
پس برای رفع این مشکل و موقعی که میخایم یه کد رو ست کنیم که مثلا تو Button1 ، یه پیام خاص رو ست کنه و تو Button2 ، یه پیام خاص دیگه رو ، باید متغییری که نام میبریم ، شماره ی همون دکمه باشه و هر بار ، با اجرای هر دفه کلیک روی دکمه ، اول اون متغییر (تو اینجا مقدار j) اور رایت بشه یا اگه مقدار آرایه ی خاص رو هم میخایم که ست کنه ، به شماره ی همون عضوی که میخایم ، اوررایت اش کنیم اون متغییر رو
یادتون باشه این مقداری که برای اندیس تو آرایه ها اوررایت میشه ، هر بار یکی بهش اضافه میشه ممولا و کلا مقدارش یکی بیشتر یا برابر آخرین عضو آرایه هست اما تو این حالت ما میخایم هر دکمه ای که اجرا میکنیم ، اون متغییر (تو اینجا مقدار j) قبلش برابر شماره ی اون عضوی بشه که ما میخایم
انگار در وهله ی اول ، فقط از همین طریق ، میشه این کار رو انجام دادخوب برا اوررایت کردن هم باید شماره ی اون دکمه رو بگیریم که انگار راهی جز زمان اجرای خود کد ینی داخل پارامتر یا آرگومان سوم ورودی بالا نداریم. پس باید این جوری بنویسین :
کد:Code = "ButtonName = Button.GetProperties(this);ButtonNumber = String.Mid(ButtonName.ObjectName, 7, -1); Dialog.Message(\"\", ButtonNumber );" Page.SetObjectScript("Button"..j, "On Click", Code); j=j+1
که موقه اجرای کد ، تو هر دکمه ، اول شماره ی دکمه رو میگیره بعد اونو مینویسه و مستقل از متغییر j عمل میکنه و هر بار هم این متغییر اوررایت و مقدارشم برابر مقدار همون شماره ی دکمه میشه (ینی رو دکمه ی 5 کلیک کنین ، این متغییر 5 میشه و بدش رو دکمه ی 9 کلیک کنین ، بدش 9 میشه) و مثل متغییر j نیست که هر بار فقط یه دونه اضافه بشه
از آقا محسنم بازم تشکر میکنم که بابتش وقت گزاشت
M3RS4D 50062 (02-04-15), nima_hl (05-08-14)
فارسی نوشتن موقه اضافه کردن متن یه شی :
باید در این مواقع ، FontScript=1 یا همون برابر DEFAULT_CHARSET بگیرین تا فارسی شه بجا زمانی که خودتون تو قسمت Script فونت ، گزینه ی Arabic رو انتخاب میکردین
M3RS4D 50062 (02-04-15)
یه تجربه ی خنده دار از خودمو بگم که شاید اگه کسی مثّ من فک کرد ، وقتش گرفته نشه : برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
اگه خدای نکرده یه وقت مثّ من فک کردین که سمت چپ مساوی یا همون کنار یه متغییر یا آرایه (محتوای متغییر یا مقدار بازگشتی اش که سمت راست مساوی هه منظورم نیست ها) میتونین در ادامه اش یه متغییر دیگه تعریف کنین (که علامت اش دو تا نقطه ی پی در پی هه ینی .. ) یا یک نقطه مثل فرا آرایه یا حتی آرایه ، برا اینکه به قول اوستا حامد بتونین آرایه چن بعدی داشته باشین ، یه متغییر رو از قبل تعریف کنین و با گزاشتن یه نقطه همونو کنار آرایه یا فرا آرایه تعریف کنین ، باید بگم که اشتبا میکردین مثّ من و بر روی آب ، آونگ میکوبیدین برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
البته اوستا حامد نگفت با چه زبان هایی میشه آرایه ی چن بعدی نوشت برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
مثال های اشتباه :
کد:ABC = {} ABC.ThisPage = {} ThisPage = Application.GetCurrentPage(); ABC.ThisPage[1] = "Har Meghdari"
یا
کد:ABC = "A Name" Motaghaier = "Abc" ABC..Motaghaier = 5
تو اولی مثال ، ارور شاید نده اما چیزی که شما میخاین هم درس نمیشه و عملیات اچ3 عقیم میمونه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
پس متوجه شدین دیگر؟ حداقل حداقل اش اینه که جز قضیه ی آرایه و فرا آرایه که نقطه میتونین بزارین در سمت چپ تساوی ، برا این قضیه که گفته شد ، اصلا شدنی نیست و نمیتونین بزارین و همینطور ، فرا آرایه و کلا هر آرایه ای تو لوا ابعاد نداره ینی نمیشه مثل داخل اندیس اش که میشه متغییر تعریف کرد ، در سمت چپ تساوی ، نمیشه یه متغییر دیگه تعریف کرد و خودتونو و وقت تونو بخاطر این کار ، به فنا ندین . ما به فنا دادیم و نتیجه ای حاصل نشد برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید اگه این کار شدنی بود ، یه قدرت و آسونی چن برابری تو لوا برا تعریف آرایه ممکن بود
M3RS4D 50062 (02-04-15), nima_hl (05-08-14)
ماژول ها :
بازم باید از دو جهت ازت تشکر کنم که سید . هم واسه یاد دادن این مطلب و هم این الگوریتم (ای کاش بیشتر درباره اش توضیح میدادی . فراخونی اش چجوریه؟ من فراخونی کردم array[1][1] اما جواب نداد)
کلا من اگه لیست این تاپیک که وابسته به آموزشای بچه هاست رو لیست کنم ، یه فرا آرایه ی دویست بعدی درمیاد چند بعدش تا حالا شدن گلپسران حامد و جواد و محاسنین (دو تا محسن ) و سید انجمن مون و اوستا محمد (اون یکی منظورمه) . ماشاء ا... یه انجمن هست ، دویست تا دو به دو اسم دارن . سجادین انجمن =3 تا . محسنین انجمن = 2 تا . محمدین انجمن = 2 تا فقط حامدین و جوادین موند
چقد صوبت میکنم؟ بریم سر اسب مطلب
ماژول ها ، ادغام آرایه یا فرا آرایه با توابع هست که هر عضو آرایه یا فراآرایه ، میتونه یه تابع داشته باشه . برای ساختنش همونطور که از تعریفش معلومه ، باید اول یه فراآرایه تعریف کرد و بعد میتونیم هر عضوشو یه تابع بنویسیم (مختاریم) و ملومه که توابع تعریف شده ، هر کدومشون باید یه مقدار رو برگردونن تا موقع فراخونی ، یه حاصل و نتیجه ای بدست بیاد . برای فراخونی شم فقط کافیه اسم عضو اون فراآرایه رو که یه تابع هست نام برد و چون اون یک تابع هست و ممکنه ورودی یا آرگومان داشته باشه پس باید مثل فراخونی بقیه ی توابع ، آرگومانش هم تعریف کرد.
هدف از ماژول هم تقریبا میشه گفت مثل فراآرایه هست ، برای نظم بیشتر و نوشتن تعداد خطوط کمتر و راحت تره
ماژول تنها جاییه که یه تابع میتونه اسم نداشته باشه (البته با اسم رو تست نکردم) و نحوه ی فراخونی اش که گفته شد
پس هر جا آرایه رو همراه تابع دیدین ، ممکنه ماژول باشه
یه مثال بزنم (البته همه ی اینا از مثالای بچه هاست و اینم از سید اهل انجمن ، گلپسر محمد همونطور که گفته بودم):
کد:Math = { add = function (a,b) return(a+b) end, sub = function (a,b) return(a-b) end, mul = function (a,b) return(a*b) end, div = function (a,b) return(a/b) end
Math تو مثال بالا ، فرا آرایه ایه که 4 تا عضو داره و هر عضوشم یه تابع هست.
درسته که فرا آرایه ، چند بعدی نیست اما چون داخلش متغییر داره پس آرایه ی معمولی هم نیست و فرا آرایه هست که عضو هاش اینا هستن تو مثال بالا :
کد:Math={add,sub,mul,div}
که ملومم بود و هر کدوم شون هم که برابر تابع گرفته شدن ینی هر کدوم از عضو هاش ، یه تابع ان. برای فراخونی شم کافیه مثل فراخونی فرا آرایه عمل کنین (تو پست صفه اول که همرا متغییر بودن) ینی اسم اصلی فرا آرایه رو بنویسین و یه نقطه بزارین و اسم عضو داخلی شو (یا میشه گفت اون متغییر) رو بنویسین . مثلا برا فراخونی تابعی که کار جمع رو برعهده داره ، اسم اون فرا آرایه رو این جوری فراخونی کنین :
کد:Math.add
که ملوم بود .
** یه نکته اینه که چون تو ماژول ها ، تابع ها میتونن اسم نداشته باشن ، پس باید همونطور که گفته شد ، اسم اون عضو فرا آرایه رو مثل بالا فراخونی کرد و در این حالت هم بهتره برا هر تابع یه مقدار خاص رو برگردونین که میدونین از کلمه ی return باید استفاده شه (حالا بازم مختارین . میتونین بسته به حالات مختلف ، توابع مختلفی بنویسین که اصلا مقداری رو هم برنگردونه)
موفق و پیروز و سربلند باشید
M3RS4D 50062 (02-04-15), nima_hl (05-08-14)
رشته ها در لوا به دو صورت تعریف میشن :
1- مابین دو علامت " " که بیشتر برای رشته های یک خطی به کار میره.
2- مابین دو علامت [[ ]] که بیشتر برای رشته های چند خطی به کار میره.
مثلا متغییر MyVars زیر که متغییر رشته ای هست رو به دو صورت میشه تعریف کرد :
اول :
کد:MyVars = "MyFunc = {} _DesktopFolder = 100 MyFunc.GetName = \"mohsen\""
دوم :
کد:MyVars = [[ MyFunc = {} _DesktopFolder = 100 MyFunc.GetName = "mohsen" ]]
قسمت دوم ممولا برا متغییر هایی که تو چن خط تعریف میشن ، کاربرد داره . اما فرقی تو عملکرد با هم ندارن این دو خط
تابع loadstring هم که جزء توابع اصلی برنامه نویسی خود لوا هست ، با ساختار زیر (دو تا پرانتز) که رشته رو دریافت میکنه ، اون رشته رو به متغییر تبدیل میکنه :
کد:loadstring(MyVars)()
برای استفاده از توابع اصلی خود زبان لوا ، تو این لینک بیاین
با تشکر از گلپسر محسن برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
آخرین ویرایش توسط SajjadKhati در تاریخ 12-09-14 انجام شده است
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
*MoJtAbA* (12-09-14), AMD>INTEL (12-09-14), M3RS4D 50062 (02-04-15), PUMAOC (11-12-14)
فرا آرایه (MetaTable) :
اول جا تشکر ویژه داره که از گلپسر اشکان کنم که واقعا تو آموزشش بهم کمک کرد برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
اونی که تو صفحات قبل گفته شد به عنوان فرا آرایه ، فرا آرایه نبود (تا امروز فک میکردم بود) برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید . آرایه ی چند بعدی بود (من فک میکردم هر دو یکی ان . دست اوستا امیر درد نکنه که منو متوجه کرد) برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید بدش بگم که این چیزایی که گفته میشه ، تجربه ی من و راهنمایی اوستا اشکان هه . چون تجربه ام زیاد نیست ، ممکنه جاهایی درست مطلب گفته و جا نندازم یا حتی اشکال یا غلط بگم . هر کی که به درک کامل تر رسید ، اینجا تو این تاپیک کاملش کنه این مبحث روبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
فرا آرایه در واقع یه آرایه ای هست که با توابعی که از پیش تعریف شده برای لوا هست (که دو تا علامت آندرلاین __ کنار اسم تابع اش داره) ، 2 کار رو تو آرایه ها انجام میده :
1) اگه مقدار یا عضوی از یه آرایه ای رو فراخونی کردیم که مقدارش nil بود ، با فرا آرایه میتونیم اون مقدار رو براش تعریف کنیم که دیگه nil نباشه و مقدار داشته باشه
2) عملگر و یا نوع فراخونی و بقیه ی کارای یک یا دو آرایه رو براش تعریف کنیم . ینی مثلا بصورت عادی نمیشه دو آرایه رو با هم جمع کرد اما با این حالت میشه
اگه این دو حالت پیش بیاد ، ینی مثلا یه عضوی از آرایه ای رو بخونیم که nil باشه و براش هم فرا آرایه ست کرده بودیم قبلا ،اون عضو از آرایه بجا اینکه nil رو برگردونه ، آرایه و الگوریتم فراآرایه رو اجرا میکنه
پس فراآرایه در واقع یه جوارایی ساختش ، به ماژول ها شباهت داره (آرایه ای که داخلش تابع تعریف میشه) . این توابع هم این طور نیست که آرگومان و ورودی هاش هر چی دلمون بخاد باشه چون این توابع تو لوا تعریف شده هست و باید با همون تداد آرگومانی این توابع رو بسازیم که تو لوا تعریف شد. لیست این توابع و عملکرداشونو میتونین بصورت کامل تو جدول قسمت پایین این صفه ببینین .(البته همونطور که گفته شد ، چون این توابع ها از پیش تعریف شده ان و تعداد و نوع آرگومان و ورودی هاشون باید همون جوری باشه که تعریف شد و تو اون لیست ، این ویژگی هاش و راهنماش نیومد ، فقط باید از مثال هاش پی ببرین و بازم چون همه ی توابع رو تو اون لینک مثال نزد ، شما میتونین با نوشتن اسم تابع و تو ادامه function example in lua ، تو سایتا سرچ کنین )
فرا آرایه هم با با تابع setmetatable برا یه آرایه تعریف میشه. این تابع ، دو آرگومان داره که تو آرگومان اولش آرایه ای که میخاین فرا آرایه براش ست کنین و نسبت بدین رو مینویسین و آرگومان دوم هم فراآرایه (که معلومه و گفته شد از نوع آرایه هست) رو مینویسین
تا اینجا دید یو آندرستود؟ ندید یو ؟ ببینین یو برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
بوریم مثالِ سر وقت (بریم سر وقت مثالا . مازندرانی رو باید یاد بگیرینا . از انگلیسی هم واجب تره برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) :
نگا کنین در واقع تابع setmetatable دو کار میکنه . اول اینکه برا آرایه ، فرا آرایه ست میکنه و دوم اینکه مقدار آرایه ی داده شده (که تو آرگومان اول اش میدادیم) رو برمیگردونه . مثلا تو مثال زیر :
با این مثال :کد:mytable = {} mymetatable = {} setmetatable(mytable,mymetatable)
هیچ فرقی ندارهکد:mytable = setmetatable({},{})
تو مثال اول ، آرایه ای به عنوان آرایه ی اصلی که که فرا آرایه براش میخاد تعریف شه ، بنام mytable تعریف شد و بدش یه آرایه بنام mymetatable که به عنوان فرا آرایه ای که برا mytable میخاد ست شه و خط بدشو که توضیح دادم.
تو مثال دوم که همونطور که گفته شد ، تابع setmetatable ، آرایه ای که تو پارامتر اولش تعریف شد رو برمیگردونه پس mytable = {} میشه و علاوه بر اینکه فرا آرایه (پارامتر دوم) هم برا این آرایه ست میشه
تا اینجا مثال کلی بود . حالا بریم سراغ یه مثال واقعی برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید :
تابع index__ :
یکی از مهمترین تابع برا ایجاد فرا آرای هست . کارش تعریف فراآرایه ای هست که اگه تو یه آرایه ، موقه فراخونی عضوی از اون آرایه ، اون عضوش nil باشه یا تعریف نشده باشه ، دیگه بجا برگردوندن nil ، اون فراآرایه اجرا میشه .
یه مثال :
کد:mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) if key == "key2" then return "metatablevalue" else return mytable[key] end end }) Dialog.Message("Notice", mytable.key1.."\n"..mytable.key2, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
اولا تو خط اول گفتیم که تابع setmetatable ، اولین پارامتر یا ورودی اش که آرایه هست رو برمیگردونه پس mytable یه آرایه هست اونم مقادیر و عضوهاش میشن :
دوم اینکه میریم تو خط آخر برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید . خط آخر ، میگه که key1 امین عضو از آرایه ی mytable رو فراخونی کن که خوب تعریف شده هست و مقدارشم برابر رشته ی value1 هه که موردی نداره و در ادامه ی Dialog.Message میگه Key2 امین عضو از آرایه ی mytable رو فراخونی کن . Key2 امین عضو از آرایه ی mytable وجود دارد عایا؟ برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ندارد عایا . پس چه میشود عایا؟ برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید چون مقدارش برابر nil هه پس فرا آرایه ینی پارامتر دوم setmetatable اجرا میشه.کد:mytable = {key1 = "value1"}
قبل از ادامه ، اول بزارین نحوه ی تعریف و اصول اولیه ی فرا آرایه گفته شه :
1) همونطور که گفته شد ، برا تعریف تابع ی فراآرایه ، از توابع از پیش تعریف شده ی لوا استفاده میشه (مثل index__ در این مثال و چن تا مثال دیگه در ادامه گفته میشه) که برا استفاده از راهنماش گفته شد
2) تعداد و نوع آرگومان و حتی اسم این توابع دست ما نیست و بازم باید از توی مثال های راهنمای انگلیسی متوجه شین (من انگلیسی ام عالیه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) و اغلب آرگومان هاشم راحت میشه حدس زد (تجربه ای متفاوت از حس شیشمبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) و اغلب تعداد آرگوماناش به تعداد آرایه ی استفاده و درگیر شده هست که اغلب 2 تاست و اغلب هم نوع آرگومان های این توابع هم از نوع آرایه هست و تو اغلب موارد هم آرگومان اول ، اون آرایه ی اصلی مونه که میخایم تغییرات روش انجام بشه
3) برا تعریف تابع تو فراآرایه ها ، مثل مثال بالا عمل کنین ینی اسم تابع مورد نظرتونو برابر بگیرین با کلمه ی فانکشن و بد براش آرگومان تعریف کنین . به این حالت تعریف کنین ، نمیشه ها چون علامت آندرلاین داره و ارور میده :
اغلب در اغلب شد برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید خو بَیته مِرِه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید شام زیاد خوردما ، شکمم پره ، خابم میاد. جاتون پر ، ماکارونی داشتیمبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنیدکد:function __index(mytable, key)
حالا بریم ادامه ی بحث درباره ی آرگومان دوم مثال بالا یا همون فراآرایه اش :
خوب تو این تابع index__ آرگومان هاش این جوریه که (گفته شد که نوع آرگمان اش رو باید تو مثال ها ببینین که از پیش تعریف شده هست و به احتمال بسیار زیاد قابل تغییر نیست) ، وقتی اسم و عضو آرایه فراخونی میشه ، قسمت اسم آرایه ، به یه پارامتر و قسمت عضو آرایه ، به یه پارامتر دیگه تو تابع مورد نظر (در اینجا تابع index__) ارسال میشه . الان تو قسمت Dialog.Message که mytable.key2 فراخونی شد ، اسم آرایه که mytable هه به پارامتر اول تابع index__ که از نوع آرایه هست ارسال شد و اسم key2 به پارامتر دوم این تابع که این بار از نوع رشته هست (ینی key2 بصورت رشته) وارد اونجا میشه که این نوع اش رو که تو اینجا تو این پارامتر ، رشته هست که گفته شد از پیش تعریف شده هست رو تو مثال ها میتونین پیدا کنین
ینی الان تو تابع index__ هر جا mytable نام برده شد ، همون آرایه mytable و هر جا key برده شد ، همون رشته ی "key2" هه منظورش (پس ورودی اول این تابع از نوع آرایه و ورودی دومش از نوع رشته هست)
بقیه دَوِّه فِردا . مِه چِش کور بَیِّه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
خا کجا بودیم؟ آها رو کره ی زمین بودیم برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید بریم ادامه مبحث
خوب چون تو mytable.key2 مقدار پارامتر key رشته هه و برابر key2 ینی :
هست ، و تو شرط تابع index__ این شرط گزاشته شده ، پس تابعش مقدار رشته ای metatablevalue رو برمیگردونه ینی بجا mytable.key2 ، رشته ی metatablevalue برگردونده و چاپ میشه تو Dialog.Messageکد:key = "key2"
راستی بجا نوع نگارش تابع تو خط بالا (الگوریتم تابع نه ها) میشه این طور هم نوشت اما من با روش بالا راحت ترم :
حالا بریم سر وقت مثال دوم از نوع دوم که تعریف عملگر و فراخونی و ... بین دو آرایه بود بود.کد:mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } }) Dialog.Message("Notice", mytable.key1.."\n"..mytable.key2, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
اول تعریف عملگر بین دو آرایه :
تو توضیحش اینکه اولا تابع add__ دو تا آرگومان داره که اولیش آرایه اول ارسال میشه (قبل علامت جمع یا +) و برا دومیش آرایه ی دوم ارسال میشه (بعد علامت جمع در آرایه ها) و همونطور که از مثال هم معلومه ، تابع اولی که mytable هست و تو خط اول که پارامتر اول setmetatable هست ، تعریف شد، به عنوان پارامتر اول ، به تابع add__ فرستاده میشه و بعد علامت به علاوه که آرایه دوم و secandtable هست ، به عنوان پارامتر دوم به این تابع ارسال میشهکد:mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table.maxn(newtable) do table.insert(mytable, table.maxn(mytable)+1,newtable[i]) end return mytable end }) secondtable = {4,5,6} mytable = mytable + secondtable for k,v in ipairs(mytable) do Dialog.Message("Notice", k.."\n"..v, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end
خوب حالا تو خط دهم ینی mytable = mytable + secondtable که مثل مثال قبل نیست که مقدار یه آرایه nil باشه و فراآرایه جاش اجرا بشه. پس چجوریه که با اجرای این خط فراآرایه اجرا میشه؟ فراآرایه ای که برا یه آرایه ست شد ، هر بار که اسم اون آرایه برده شد ، چک میکنه ببینه فراآرایه ای مناسب با عملی که براش تعریف کردیم ، تعریف شد یا نه . اگه تعریف شده بود فقط اجراش میکنه . ینی الان تو مثال بالا ، اگه یه آرایه ای رو فراخونی کنین که مقدارش nil باشه ، ارور میده چون فراآرایه ای که براش تعریف شد بخاطر اینکه تابع مورد نظر (index__) رو نداره ، اصلا اجرا نمیشه در این حالت
خوب حالا با اجرا شدن خط دهم ینی mytable = mytable + secondtable پارامترهای ارسالی که گفته شد و فراآرایه اجرا میشه . تو خط سوم :
تابع table.maxn(newtable) ، با گرفتن اسم آرایه ، تعداد عضو هاش رو برمیگردونه که همون کار علامت # رو میکنه . ینی میتونین بجا خطوط بالا بنویسین :کد:for i = 1, table.maxn(newtable) do table.insert(mytable, table.maxn(mytable)+1,newtable[i]) end
و دیگه ملومه که عضوهای آرایه ی newtable رو به عضوهای آرایه mytable اضافه میکنه . سر آخر هم همین آرایه ی mytable رو این تابع برمیگردونه (تو خطوط بالا) و بهتر ازم میدونین که ینی بجا mytable (سمت چپ تساوی خط دهم) ، مقدار mytable برگردونده میشه که شامل عضوهای اضافه شده ی آرایه ی newtable به آرایه ی خودشه ینی این :کد:for i = 1, #newtable do table.insert(mytable, #mytable+1,newtable[i]) end
حالا مثال بدی (فراخونی آرایه . میدونین دیگه منظور همون تغییر عملکرد در فراخونی یا در واقع ست کردن فراآرایه ای برا فراخونی یه آرایه هست) :کد:mytable = { 1, 2, 3 ,4,5,6}
برا فراخونی (ینی تغییر عملکرد و رفتار فراخونی یه آرایه یا در واقع ست کردن فراآرایه برا تغییر نوع فراخونی) از تابع call__ استفاده میکنیمکد:mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 for i = 1, #mytable do sum = sum + mytable[i] end for i = 1, #newtable do sum = sum + newtable[i] end return sum end }) newtable = {10,20,30} Dialog.Message("Notice", mytable(newtable), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
خوب همونطور که میدونین این فراآرایه تو مثال بالا ، موقعی اجرا میشه که خط آخر اجرا بشه ینی وقتی که تو پارامتر دوم گفتیم mytable(newtable)
دیگه ورودی این تابع call__ و الگوریتم هایی که توش بکار رفت کاملا مشخصه دیگه برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
مقدار بازگشتی شم تو این مثال 70 هه
تابع دیگه هم tostring__ هه که برا تغییر عملکرد فراخونی هه که تو مثال سایت بالا اومد
راستی این مثالا از همون لینکی که تو بالا داده شد گرفته شد (از گلپسر سید هم بخاطر معرفی این سایت ممنونمبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید )
امیدوارم براتون مفید بوده باشه این آموزش
بازم دسِّت درد نکنه اوستا اشکان برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
AMD>INTEL (24-09-14), M3RS4D 50062 (02-04-15), nima_hl (24-09-14), PUMAOC (11-12-14)
چند نکته ی مهم درباره تابع :
1) تابع با چندین مقدار برگشتی :
همونطور هم که تو قضیه ی دیتابیس تو کتاب اوستا حامد گفته شد (تو فیلم دیتابیس sql و ... گفته نشدبرای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) ، یه تابع میتونه یا میتونیم کاری کنیم که بجا یه مقدار ، چندین مقدار رو برگردونه که در این صورت باید به تعداد مقدار بازگشتی اون تابع (مثلا فرض میکنیم 3 تا مقدار بازگشتی داره) ، باید به همون تعداد ، متغییر براش تعریف کرد و همه ی متغییرهاشو با ویرگول از هم جدا کرد . مثلا تو مثال زیر :
تابع بالا که اسمش func هست ، 3 مقدار Val1 و Val2 و Val3 رو برمیگردونه . که موقع فراخونیش هر کدوم به ترتیب ، دقیق تو متغییرهاش (که موقه فراخونی استفاده کردیم) ذخیره میشن ینی مقدار بازگشتی Val1 (که تو مثال بالا که مقدارش 300 هست) تو متغییر Plus و مقدار Val2 (که تو اینجا 20000 هه) تو multiplication و مقدار Val3 (که تو اینجا 100 هه) تو متغییر Minus ذخیره میشهکد:function func(a,b) Val1 = a+b Val2=a*b Val3 = a-b return Val1,Val2,Val3 end Plus,multiplication,Minus = func(200,100) Dialog.Message("Notice", "a+b = "..Plus.."\na*b = "..multiplication.."\na-b = "..Minus, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
ینی اولین مقدار بازگشتی تو اولین متغییر تعریف شده و دومین مقدار بازگشتی تابع ، تو دومین متغییر تعریف شده و ... به همین ترتیب ذخیره میشه
2) اجرای تابع (تابعی که در نرم افزار از پیش تعریف شده باشه) داخلی :
همیشه اگه دو تابع داخلی تو در تو باشه ، اول تابع داخلش اجرا میشه و در مرحله ی بعد ، مقدار بازگشتی تابع فراخونی شده برگردونده میشه مثلا :
تو مثال بالا ، اول پیام Your message here داده میشه و بعد مقدار بازگشتی تابع Dialog.Message که عدد هست رو تو پیام دوم میدهکد:Dialog.Message("Notice", Dialog.Message("Notice", "Your message here.", MB_YESNO, MB_ICONINFORMATION, MB_DEFBUTTON1), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
3) اجرای چند تابعی که خودمون میسازیم :
دقیق عملیاتش برعکس بالایی هست . ینی اونجا تابع آماده ی داخل پروژه بود اما اینجا تابعی که خودمون میسازیم (چند تا تابع تو هم) . تو اینجا بر عکس حالت بالا ، هیچ وقت تابع داخلی حتی اجرا هم نمیشه جز اینکه تو تابع بیرونی تر هه (تابع خارجی تر یا اولیه) اون تابع داخلی اش فراخونی بشه یا برگردونده بشه
مثال :
تو مثال بالا اگه تابع داخلی تره (Sec) تو تابع خارجی تره (Init) فراخونی نمیشد یا برگردونده نمیشد ، تابع Sec هیچ وقت اجرا نمیشد . یه نکته ی دیگه هم اینه که تو این حالت نمیتونیم مستقیما تابع داخلی رو فراخونی کنیم چون ارور میده و تابع داخلی یه تابع رو بصورت مستقیم تشخیص نمیده ینی نمیتونیم این جوری بنویسیم :کد:function Init(a,b,c) function Sec(a,b) ABC = a+b+5 return ABC end return Sec(a,b) end Nm = Init(10,20,30) Dialog.Message("Notice", Nm, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
4) تابع با ورودی و آرگومان متفاوت :کد:function Init(a,b,c) function Sec(a,b) ABC = a+b+5 return ABC end return Sec(a,b) end Nm = Sec(10,20) Dialog.Message("Notice", Nm, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
همونطور که اوستا محمد (سید اهل انجمن خودمون برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید ) تو لینک زیر گفت :
http://persiancoders.com/1393/04/%D8...4%D8%AE%D8%B5/
برای مشخص کردن تابع بدون مشخص کردن ورودی یا آرگومان باشه ، از سه نقطه ... استفاده میشه . بدش هم حتما ورودی ها رو به روش زیر یا همون روشی که تو لینک بالا گفته شد ورودی ها رو تو آرایه ریخت و با بدست آوردن تعداد آرایه (تعداد تو لوا رو با علامت # نشون میدن مثلا تو مثال زیر تو خطی که نوشت #arg ینی تعداد آرایع ی arg) به الگوریتم اون تابع میپردازیم :
برا فراخونیش تو دکمه :کد:function average(...) result = 0 local arg={...} for i,v in pairs(arg) do result = result + v end return result/#arg end
حالا گلپسران اساتید ، هر جا احساس کردین نیاز به توضیح داره برا این قسمت ، حتما بگین . ممنون برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنیدکد:Debug.Print(average(1,4,3,5,4).."\r\n"); --result = 3.5 Debug.Print(average(1,4,5,4,4,3,7,8,9,4,2,9).."\r\n"); --result = 5 Debug.Print(average(2,9)); --result = 5.5 Debug.ShowWindow(true);
آخرین ویرایش توسط SajjadKhati در تاریخ 11-12-14 انجام شده است
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
AMD>INTEL (11-12-14), M3RS4D 50062 (02-04-15), nima_hl (11-12-14), PUMAOC (11-12-14), مهدی بهادرفر (11-12-14)
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()
گلپسران اگه اشکالی چیزی دیدین ، خوشحال میشم راهنمایی کنین
موفق و پیروز و سربلند باشین . مِرِه خو بَیته برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
AMD>INTEL (11-12-14), dayaoo (09-02-15), M3RS4D 50062 (02-04-15), nima_hl (12-12-14), مهدی بهادرفر (11-12-14)
تو این آموزش رسمی کتابی نوشته شد برای مشاهده این لینک/عکس می بایست عضو شوید ! برای عضویت اینجا کلیک کنید
1) بلاک ها (Block) :
در واقع هر شرط و حلقه و کلا هر چیزی که به کلمه ی کلیدی end ختم شود را میشود یک بلاک نامید
اما منظور ما در اینجا از بلاک ، شرط و ... نیست . ساختاری به این شکل است :
کد:do --body end
معمولا این نوع بلاک ، اغلب برای تعریف متغییر محلی بیشترین کاربرد را دارد.
2) متغییر محلی (local variable) :
متغییر محلی ، متغییری ست که اگر در بلاک ای تعریف شده باشد ، فقط تا پایان اجرای کدهای آن بلاک اعتبار دارد (تا پایان end) و در حافظه ی اصلی میماند و بعد از اتمام آن بلاک حذف میشود و اگر بلاکی تعریف نکنیم ، تا پایان اجرای آن رویداد باقی میماند
در واقع متغییر محلی 2 کاربرد اساسی دارد . اول برای مدیریت جزئی حافظه ی رم و دوم برای اینکه اگر شک داریم و نمیدانیم اسمی از متغییری را که به عنوان نام متغییر محلی که داریم مینویسیم ، جای دیگری بکار بردیم یا نه و کلا نگران اوررایت شدن آن متغییریم ، از متغییر محلی استفاده میکنیم
برای درک بهتر ، میتوانید این مثال را ببینید که در هر بلاک ، متغییر محلی ، فقط در همان بلاک اعتبار دارد (گویی برای هر متغییر محلی تا پایان آن بلاک ، فضای جداگانه در حافظه اختصاص داده میشود ، صرف نظر از متغییری با همان نام که قبلا ایجاد شده بود یا نه (و آیا این متغییر قبلا از نوع محلی بود یا سراسری) و بعد از اتمام آن پاک میشود) :
کد:do local loc=5 do local loc="x" do local loc=1589 Dialog.Message("Notice", loc, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Dialog.Message("Notice", loc, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Dialog.Message("Notice", loc, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end Dialog.Message("Notice", type(loc), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
البته متغییر محلی را میتوان به تابع یا آرایه ها هم اختصاص داد . مثلا در مثال های زیر که بخاطر بودن تابع و آرایه در یک بلاک و فراخوانی آنها در بلاکی دیگر ، ارور میدهند (بخاطر nil بودنشان) :
وکد:do local funct function funct(a) a=a+1 return a end end Dialog.Message("Notice", funct(1), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
کد:do local t={5,98} end Dialog.Message("Notice", t[2], MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
نکته ای که در متغییرهای محلی باید دقت داشت این است که اگر در بلاکی (هر بلاک و حلقه و ...) ، متغییر محلی ای تعریف کردیم و اگر در یک بلاک دیگر (مثل تابع) آن متغییر را فراخوانی کردیم ، اگر از قبل مقدار نداشت که nil میشود وگرنه به مقدار قبل خود بازمیگردد. مثال :
کد:function examp() Dialog.Message("Notice", type(loc), MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1); end do local loc=4 examp() end
که در تابع examp ، متغییر loc که در بلاکی دیگر ایجاد شد اما از همان بلاک ، تابعی فراخوانی شده است که داخل آن تابع ، متغییر محلی بلاک دیگر فراخوانی شده است ، مقدارش nil است
با تشکر از تمام کسانی که در این آموزش سهیم بودند
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
mohammad- (28-06-16)
یک نکته کوچک درباره تابع :
ایجاد و فراخوانی آرایه به روشی دیگر :
اگر آرایه ای داشته باشیم که key (یا به اصطلاح سمت چپ تساوی آن ، در متغییری ذخیره شده باشد) ، مثل متغییر foo و x و y در آرایه ی زیر باشد:
کد:t={foo="bar",x=5,y=true}
به 2 حالت میشود آنرا فراخوانی کرد که اول به این گونه:
کد:t.foo t.x t.y
برابر است با نوع دوم اش به این گونه :
کد:t["foo"] t["x"] t["y"]
برای ایجاد آرایه هم میشود key ها را بصورت در هم شماره بندی و مقدار دهی کرد یعنی :
کد:t={[3]=12,[7]="salam",[1]="word",[10]=653} Dialog.Message("Notice", t[1].."\n"..t[3].."\n"..t[7].."\n"..t[10], MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
که [1]t برابر رشته ی "word" و [3]t برابر 12 و [7]t برابر رشته ی "salam" و [10]t برابر 653 هست . توجه کنیم که در این حالت بقیه ی مقادیر nil هست مثل [2]t و ... و هم اینکه نباید در این حالت که همه ی key ها شماره گذاری شده اند ، بعضی از آنها را شماره گذاری نکنیم مثلا این طور صحیح نیست :
کد:t={[3]=12,"salam",[1]="word",653}
دانلود فیلم آموزش برنامه نویسی Visual Studio C#.Net
فیلم آموزش کامل Autoplay Media Studio
وقتی انسان ، حیوان هست ، پس قیمت میتونی براش بذاری ولی وقتی انسان حَیّ مُتِاَلِّه هست که قیمت نداره ، بها داره. "دکتر حسن عباسی"
|
1 کاربر در حال مشاهده این موضوع. (0 عضو و 1 میهمان)
Bookmarks