تغییرات جدید نسخه 8 زبان PHP چیست؟ (قسمت پنجم)

What's New in PHP 8? - Part 5

09 مرداد 1399
تغییرات جدید نسخه ی 8 زبان PHP چیست؟ (قسمت پنجم)

به جلسه ی پنجم از ویژگی های جدید PHP 8 خوش آمده اید! در قسمت های قبل با مفاهیم مختلفی مانند JIT و انواع درخواست های جدید در RFC مانند ترتیبی کردن ایندکس در آرایه هایی با ایندکس منفی، معرفی union type ها، همسان سازی Signature های توابع و غیره آشنا شدیم. حالا نوبت بررسی موارد باقی مانده و ویژگی های جدید زبان PHP است.

دستور throw

در زبان PHP تقسیم بندی های مختلفی برای شناسایی کدها و دستورات وجود دارد که statement یکی از آن ها است. هر اسکریپت PHP از مجموعه ای از statement ها تشکیل شده است و هر statement می تواند یک عملیات انتساب، صدا زدن تابع، حلقه ها، عبارات شرطی و غیره باشد. اکثر Statement ها با علامت نقطه ویرگول (;) تمام می شوند. از طرفی یکی دیگر از واحدهای شناسایی کدهای PHP عبارت یا Expression ها هستند. documentation رسمی PHP می گوید بهترین و دقیق ترین تعریف برای Expression ها بدین صورت است: «هر چیزی که دارای مقداری باشد» بنابراین ساده ترین expression ها همان متغیرها و ثابت های PHP هستند. یکی از statement های معروف، throw است بنابراین نمی توانیم از آن در قسمت هایی از کد استفاده کنیم که نیاز به expression دارد.

یک RFC جدید پیشنهاد داده است که throw به یک expression تبدیل شود تا بتوانیم در همه جا از آن استفاده کنیم. به طور مثال در Arrow function ها و null coalesce operator ها و ternary and elvis operators ها و الی آخر. کد زیر از همین RFC آمده است:

$callable = fn() => throw new Exception();

// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
 
// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();

در حالت نمی توانیم از throw new استفاده کنیم اما با نسخه ی جدید PHP می توانیم این کار را انجام بدهیم.

معرفی Weak Map ها

Weak Map ها مجموعه ای از داده ها (شیء ها) است که در آن key ها به شکل ضعیف به هم متصل هستند. اتصال ضعیف یعنی از Garbage collection در امان نیستند. برای درک این جمله باید با مفهوم garbage collection در زبان های برنامه نویسی آشنا شوید. کلمه ی garbage به معنی «آشغال» یا «ضایعه» و کلمه ی collection به معنی «جمع آوری» می باشد بنابراین garbage collection یعنی زباله روبی! اما این عبارت در زمینه ی برنامه نویسی معنی خاص خود را دارد و معادل بازیافت حافظه است. یعنی چه؟

زمانی که شما یک متغیر را تعریف می کنید، این متغیر در مموری سیستم جا می گیرد (زمانی که کدها اجرا شود) و در صورت نیاز تغییراتی روی آن اعمال می شود یا اطلاعاتی از آن خوانده می شود (بسته به اینکه چه کدهایی نوشته باشید) اما بالاخره اجرای برنامه ی شما متوقف می شود یا حداقل قسمتی از آن متوقف می شود. مثلا اگر از کلاس مشخصی یک نمونه یا شیء ساخته باشیم این شیء در مموری خواهد بود و فضای مموری را اشغال می کند تا زمانی که دیگر به آن نیاز نداشته باشیم. اگر نیاز ما به این شیء برطرف شد، باید آن را از مموری دور بیندازیم تا فضای مموری را خالی کنیم در غیر این صورت مموری ما آنقدر اشغال می شود که دیگر جایی برای چیزی نیست. به این فرآیند بازگردانی مموری GC یا garbage collection می گویند که به نوعی در تمام زبان های برنامه نویسی پیاده سازی شده است. در بعضی از زبان های low-level (زبان هایی که به machine code نزدیک تر هستند) عملیات GC توسط کتابخانه ها یا به صورت دستی و توسط خود توسعه دهنده انجام می شود. مثلا در زبان C توسعه دهنده باید با دو تابع ()malloc و ()dealloc خودش فضای مموری را به اشیاء مختلف اختصاص داه و خودش هم آن فضا را پس بگیرد اما در زبان هایی مانند جاوا اسکریپت تمام این عملیات به صورت خودکار انجام می شود.

در نسخه ی 7.4 زبان PHP قابلیتی به نام weak references ها ارائه شد. در کلاس  WeakReference می توانیم یک ارجاع (reference) به یک شیء را حفظ کنیم البته به طوری که باعث جلوگیری از نابودی خود شیء نشود (یعنی جلوی عملیاتی مثل garbage collection یا حذف دستی شیء را نگیرد). شاید در ابتدا این توضیح کمی پیچیده باشد بنابراین بگذارید بیشتر توضیح بدهم. به مثال زیر توجه کنید:

$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());

در این مثال یک weak referece (ارجاع ضعیف) به متغیر object$ داریم. نتیجه ی اولین var_dump بالا به شکل زیر خواهد بود:

object(stdClass)#1 (0) {}

اما نتیجه ی var_dump دوم فقط NULL است چرا که شیء مرجوع از بین رفته است (به خاطر دستور unset). این کد بدون خطا و به همان صورتی که گفتم اجرا شده است. در حالت عادی اگر بین این دو، ارجاعی داشتیم چه اتفاقی می افتاد؟ ارجاع عادی جلوی نابودی شیء اول (متغیر object$) را می گرفت! استفاده از weak reference ها معمولا در ساختار های cache می باشد.

حالا به گفته ی آقای Nikita Popov قابلیت weak reference ها واقعا کاربرد چندانی ندارند اما weak map ها دارای پتانسیل کاربردی هستند. Popov می گوید نمی توانیم یک weak map بهینه را با weak reference ها پیاده سازی کنیم چرا که در weak reference ها قابلیت اضافه کردن یک callback برای حذف شیء را نداریم. به همین خاطر RFC جدید کلاس weakmap را اضافه کرده است تا بتوانیم اشیائی بسازیم که به عنوان کلیدهای weakmap استفاده شوند به طوری که جلوی نابودی چیزی را نگیرند و اگر reference دیگری به آن ها نداریم، کلید های شیء نابود شوند.

این قابلیت در فرآیند های سنگین و طولانی باعث جلوگیری از memory leak (فرآیندی که در آن برنامه ی ما قادر به رها سازی صحیح مموری و آزاد کردن آن برای استفاده نیست در حالی که اصلا به آن نیاز ندارد) و بهبود سرعت برنامه می شود. مثال زیر از RFC ذکر شده است:

$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;
var_dump($map);

در نسخه ی 8 زبان PHP کد بالا نتیجه ی زیر را خواهد داشت:

object(WeakMap)#1 (1) {
	[0]=>
	array(2) {
		["key"]=>
		object(stdClass)#2 (0) {
		}
		["value"]=>
		int(42)
	}
}

در صورتی که می خواهید کد بالا را در عمل اجرا کنید به لینک https://3v4l.org/o6lZX/rfc#output بروید. حالا اگر شیء بالا را unset کنیم، کلید (key) به صورت خودکار از weak map حذف می شود:

unset($obj);
var_dump($map);

پس از اجرای کد بالا (unset کردن شیء) نتیجه ی ما به شکل زیر خواهد بود:

object(WeakMap)#1 (0) {
}

این RFC با تمام آرا و بدون هیچ رای مخالفی تصویب شده است.


سایر قسمت‌های این مبحث را در لینک‌های زیر مطالعه کنید:

تغییرات جدید نسخه 8 زبان PHP (قسمت اول)
تغییرات جدید نسخه 8 زبان PHP (قسمت دوم)
تغییرات جدید نسخه 8 زبان PHP (قسمت سوم)
تغییرات جدید نسخه 8 زبان PHP (قسمت چهارم)
تغییرات جدید نسخه 8 زبان PHP (قسمت ششم)

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.