به عنوان یک توسعه دهنده معمولا با زبان ها، ابزار ها و یا حتی فریمورک هایی آشنا میشیم که خصوصیات اونها ممکنه ما رو شگفتزده کنه. بعضی مواقع این خصوصیات به قدری قدرتمند هستند و به قدری تفاوت ایجاد میکنند، که سخته اونها رو نادیده بگیریم.
تقریبا ۲-۳ سالی میشه که زبان قدرتمند Rust نظر من رو به خودش جلب کرده، در این پست کمی با زبان Rust آشنا میشیم و از خصوصیات، ویژگی ها و نقاط قوتش میگیم; همچنین نحوه نصبش رو با هم بررسی میکنیم و طی پست های بعدی به بررسی اصول اولیه در این زبان میپردازیم.
زبان Rust زبانی مولتی پارادایم هست، که نسخه اولیش در سال ۲۰۱۰ توسط Graydon Hoare
(یکی از توسعه دهندگانی که در پروژه تحقیقات Mozilla بود) ارائه شد که بعدها در سال ۲۰۱۵ نسخه ۱.۰ این زبان به طور رسمی منتشر شد. زبان Rust اوپن سورس هست و از سایر مشارکت کنندگانش میشه به (دِیو هرمن) Dave Herman
(مدیر استراتژی تحقیقات Mozilla) و Brendan Eich
(سازنده زبان جاوااسکریپت و بنیانگذار Mozilla) اشاره کرد.
تمرکز این زبان روی سرعت، امنیت حافظه (بدون استفاده از Garbage Collection) و پردازش موازی هست; و این باعث شده تا ازش برای ساخت دامنه وسیعی از نرمافزار ها استفاده بشه مثل: گیم انجین ها، سیستم عامل ها ، فایل سیستم ها، ساخت Restfull API و شبیه سازی های مربوط به واقعیت مجازی (Virtual Reality Simulations) و حتی در این بین این زبان پتانسیل خیلی خوبی برای برنامهنویسی های تراشه ها و میکروکنترلر ها نشون داده. (از اونجایی که کدهای Rust مستقیما به کدهای اسمبلی کامپایل میشند، میشه ازش در محیط هایی بدون حظور سیستم عامل هم بهره برد)
زبان Rust امسال برای پنجمین سال متوالی هست که دوستداشتنی ترین (most loved) زبان برنامه نویسی در استک اورفلو شناخته میشه
و این محبوبیت بیدلیل نیست.. زبانی جوان و تازه پا گرفته که در تمام بنچ مارکها داره با ++C مقایسه میشه; اما علت این همه سر و صدا چیه؟ در این نوشته قصد دارم همین رو توضیح بدم.
عموما زبان های برنامه نویسی به ۲ دسته سطح پایین و سطح بالا تقسیم میشند.. (هر چند که سطح یک زبان یک مسئله نسبی هم هست. مثلا هر چند که C زبان سطح پایینی هست اما در مقایسه با اسمبلی سطحش بالاست.)
زبانهای سطح پایینتر (مثلا C) سرعت قابل توجهی دارند و از اونجایی که مستقیما با حافظه در ارتباط هستند، برای کار با سخت افزار گزینه خوبی هستند اما در عین حال چالش های خودشون رو هم دارند.. (هر چقدر دسترسی ما به حافظه و دستکاری اون بیشتر میشه، باید دقیق تر عمل کنیم.) معمولا پروسه دیباگ کردن در این زبان ها کمی پیچیده تره.
از طرف دیگه زبانی های سطح بالاتر مثل روبی و پایتون، ممکنه که پرفرمنس زبانهای سطح پایین رو نداشته باشند; اما نوشتن و خوندن کدهاشون آسون تره و خودشون حافظه رو مدیریت میکنند; و در نهایت دیباگ کردن کدهاشون ساده تر هم هست.
پس به عبارتی: در زبان های سطح پایین ما کنترل بیشتر و امنیت کمتری رو داریم.. اما در زبان های سطح بالا کنترل کمتر و امنیت بیشتری رو داریم
حالا زبان Rust سعی داره تا نقاط قوت این دو سطح رو با هم ترکیب کنه:
در این مرحله ممکنه یه سوال مطرح بشه: با توجه به این ترکیب، پس زبان Rust در کدوم سطح قرار میگیره؟ زبان Rust هنوز هم یک زبان سطح پایین حساب میشه.. یکی از دلایلی که اکثرا با ++C مقایسه اش میکنند، همینه.
کامپایلرهای Rust و ++C هر دو دستورالعمل های native برای CPU تولید میکنند و هیچ لایه تفسیری میانی ندارند. تفاوت اصلی بین اونها اینه که Rust حاوی یک مکانیزم محافظ داخلی هست که اگر شما بخواهید کار خطرناکی با مدیریت حافظه انجام بدید، شما رو متوقف میکنه. Rust به شکل پیشفرض یک زبان امن هست. (Rust is safe by default) تمام دسترسی ها به حافظه چک میشند => پس خراب کردن (Corrupt) حافظه حتی به شکل تصادفی هم ممکن نیست; اما به این معنی نیست که شما دیگه نتونید کاملا حافظه رو مدیریت کنید; اگر واقعا بدونید که دارید چکار میکنید، میتونید از کلیدواژه unsafe
استفاده کنید و این مکانیزم رو نادیده بگیرید.
در مقابل زبان هایی مثل Java, PHP, Javascript, C#, Python, Ruby و ... یک رانتایم یا ماشین مجازی دارند که یک لایه رو بین کد شما و سیستمی که اون رو اجرا میکنه به وجود میارند. مثلا در زبان #C میشه از ابزاری مثل .NET Native
استفاده کرد و برنامه #C رو به عنوان یک اپلیکیشن نیتیو کامپایل کرد و یک پرفرمنس نزدیک به نیتیو رو هم داشت; اما این پروسه باز هم با اتفاقی که در زبانهای Rust و ++C میفته، متفاوته..
زبان Rust یک زبان Strongly-typed و Statically-typed هست. Statically به این معنا که انواع تمام داده ها در زمان کامپایل شدن، مشخص هستند. و Strongly به این معنا که این انواع مختلف داده ها، از نوشتن برنامه های غیر صحیح جلوگیری میکنند. پس یک کامپایل موفق به این معنی هست که ما تضمین خوبی برای اجرای کدهامون داریم. اگر بخواهیم جای Rust رو در نمودار زیر حدس بزنیم اصلا کار مشکلی نیست.. زبان Rust در گوشه بالا سمت راست قرار میگیره.
یکی از مشخصه های بارز این زبان سرعته. زبان Rust مکانیزم هوشمندانه ای برای مدیریت حافظه داره و به هیچ Garbage Collection ی نیاز نداره (Rust از مفاهیمی مثل Borrowing و Ownership استفاده میکنه، سیستمی بسیار هوشمندانه که حتما بررسی خواهیم کرد) . در اکثر زبان ها Garbage Collection همیشه داره در رانتایم اجرا میشه تا از خطاهای احتمالی جلوگیری کنه. اما Rust در حین رانتایم کاری انجام نمیده. چون اگر کد ما باگ یا مشکلی داشته باشه در مرحله کامپایل کردن اصلا چیزی Build نمیشه. (خطای کامپایل خواهیم داشت) در این حالت ممکنه کامپایل شدن کمی زمانبر باشه اما سرعت اجرا بسیار بالاست.
زبان های سیستم باید بتونند بهترین ماشین کد ممکن رو ، با کنترل کامل به روی حافظه ایجاد کنند; که همین سیستم حافظه هوشمندانه که هیچ اضافه باری رو در بر نداره، باعث میشه Rust برای سخت افزارهای نهفته (Embedded Hardware) عالی باشه; و روی چیپهای مختلف و بدون سیستم عامل هم به خوبی کار کنه. شاید نام ابزارهایی مثل MicroPython
و JerryScript
به گوشتون خورده باشه; فریمورک های که مبتنی بر Python
و JavaScript
هستند. این ابزارها در واقع سعی دارند برنامه نویسی میکروکنترلرها رو توسط زبانهای سطح بالا ممکن کنند، اما مشکلی که وجود داره اینه که این زبان ها تفسیری و از نوع Weakly-Typed هستند و در نهایت دارند از Garbage Collection استفاده میکنند; که اینها در نهایت باعث میشه تا این زبان ها از نظر پرفرمنس نتونند با C++/C رقابت کنند. از طرف دیگه Rust وعده های مبتنی بر memory safety
و efficiency
میده که برای این نوع از برنامه نویسی کاملا واجب هست. Rust در این حیطه که عملکرد خوبی نشون داده.. اما با این وجود نوشتن سایر کدها هم در این زبان بسیار دلپذیر هست.
اگر پرفرمنس و سرعت زبان Rust بالا هست، پس چرا از Rust برای نوشتن سیستم عامل (OS) ها استفاده نکنیم؟ این کار هم انجام شده. در واقع در این لیست میتونید یک مقایسه نسبی رو بین چند پروژه مطرح این زبان ببینید. در بین این سیستم عامل ها میشه به Redox اشاره کرد; سیستم عاملی که کرنلش (که میشه گفت شبیه به Unix هست) با زبان Rust نوشته شده و کتبخونه استاندارد Rust رو پشتیبانی میکنه و یه کارهایی هم در زمینه GUI انجام داده.. مسلما Redox هنوز برای رسیدن به یک بلوغ نسبی زمان لازم داره، اگر به سیستم عامل های Unix-base علاقه دارید احتمالا از Redox هم خوشتون بیاد. این سیستم عامل متن باز (Open Source) هست و میتونید به راحتی امتحانش کنید.
یکی دیگر از زمینه های که Rust میتونه درش مورد استفاده بگیره، توسعه تحت وب هست. وب اسمبلی (Web Assembly) یک تکنولوژی نسبتا جدیده که باهاش میشه کدهای زبان های سطح پایینی مثل C و Rust و برخی دیگه زبان ها رو در مرورگرها اجرا کرد.. این تکنولوژی باعث شده تا توسعه دهنده های این زبان بتونند فریمورک های سمت کلاینت بنویسند.. مثل Yew
که الهام گرفته از React
هست. (مایکروسافت هم در Blazor از وب اسمبلی استفاده کرده، که باعث میشه بتونید با #C و HTML صفحات وب بسازید) همچنین در سمت سرور هم زبان Rust بخوبی عمل میکنه و در حال حاظر چندین فریم ورک وب داره.. مثل Actix, Iron, Gotham, nickel, Rocket و ... فریم ورک هایی که شاید هنوز به بلوغ کامل نرسیدند اما در سرعت و پرفرمنس بینظیر هستند. چند وقت پیش کتاب جالبی رو پیدا کردم، که در زمینه پیاده سازی میکروسرویس ها در Rust نوشته شده:
زبان Rust به عنوان یک پروژه تحقیقاتی در قلب شرکت Mozilla متولد میشه.. پس اگر از مرورگر فایرفاکس استفاده میکنید، جالبه که بدونید: از نسخه ۴۸ به بعد، زبان Rust در قسمت هایی از فایرفاکس هم داره استفاده میشه. (رقابت میتونه واقعا جالب باشه.. بعد از اینکه شرکت گوگل در سال ۲۰۰۹ Golang رو معرفی کرد.. دقیقا ۱ سال بعد پروژه Rust از طرف رقیب منتشر میشه; ۲ شرکتی که عمده فعالیت هاشون در حیطه وب بوده، ناگهان احساس میکنند به زبان های برنامه نویسی سیستمی خودشون نیاز دارند. و این رقابت باعث معرفی شدن ۲ زبان جدید با پرفرمنس بالا میشه.) تصویر زیر اطلاعات تله متری منتشر شده از سمت موزیلا هست، که نشون میده پس از ۱ میلیارد بار استفاده از فایرفاکس (با بخش هایی مبتنی بر Rust) هیچ مشکلی گزارش نشده.
نصب Rust خیلی پروسه سادهای هست.. کافیه کامند لاین رو باز کنید و دستور زیر رو اجرا کنید:
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
با این دستور میتونید زبان Rust رو در سیستم عامل های لینوکس، مکینتاش و ویندوز به راحتی نصب کنید. این دستور با استفاده از curl اسکریپتی رو دانلود میکنه که از طریق اون ابزار خط فرمان rustup
نصب میشه; از مهمترین مواردی که نصب میشند میشه به گزینه های زیر اشاره کرد:
زبان Rust از پکیج منیجر ساده و قدرتمندی به نام Cargo
استفاده میکنه. برای ساخت پروژه جدید، بررسی کد، پیدا کردن خطا ها، کامپایل، بیلد پروژه و همچنین مدیریت وابستگی ها از این ابزار استفاده میشه. این پکیج منیجر یک فایل Cargo.toml
درست میکنه که دقیقا کار فایل package.json
رو در یک پروژه جاوااسکریپتی انجام میده و شامل جزئیات و وابستگی های پروژه هست.
ابزار خط فرمان rustup
در واقع Toolchain Installer زبان Rust هست که کامپایلر (rustc) رو نصب میکنه.. و امکان آپدیت کردن Rust رو هم فراهم میکنه. حدودا هر ۶ هفته یک آپدیت موجود هست که میتونید به شکل زیر نسخه Rust رو به روز کنید:
rustup update
و اگر خواستید مستندات Rust رو (نسخه لوکال) در مرورگر ببینید، به شکل زیر:
rustup doc
و برای حذف Rust از روی سیستم هم، به شکل زیر:
rustup self uninstall
بعد از مراحل نصب باید دستورات زیر در سیستم شما قابل اجرا باشند و نسخه نصب شده رو نشون بدند:
برای نصب Rust در ویندوز: توجه کنید که بعضی از پکیج های Rust برای اجرا وابسته به C هستند، پس شما به یک C Compiler احتیاج دارید; که به شکل پیش فرض روی سیستم عامل ویندوز هیچ C کامپایلری موجود نیست، مگر اینکه خودتون نصب کرده باشید و یا در حین نصب ویژوال استودیو نصب شده باشه; پس قبل از نصب Rust سری به وب سایت مایکروسافت بزنید و Microsoft Build Tools for Visual Studio رو نصب کنید. نسخه ۲۰۱۳ و یا بالاتر.
و اگر روش نصب در کنسول رو نمی پسندید: میتونید به آدرس https://www.rust-lang.org/tools/install برید و فایل اجرایی مناسب با سیستمتون رو دانلود و اجرا کنید.
یکی از نکاتی که در توسعه این زبان بهش بها داده شده ثبات (Stability) هست. این نکته به همراه سایر اصولی که Rust بر مبنای اون توسعه داده شده باعث میشه Rust به عنوان یک فونداسیون مطمئن و قابل اتکا معرفی بشه.. اما اگر اوضاع دائماً در حال تغییر باشه، چنین چیزی امکان پذیر نیست. و در عین حال اگر فیچر های جدید قابل تست نباشند، ممکنه نقص های مهم تا بعد از انتشار یک نسخه کاملا مشخص نشه.
روش تیم Rust برای حل این مشکل جالبه و اسمش رو ثبات بدون رکود (Stability without Stagnation) گذاشتند. اصل این موضوع به این اشاره داره که شما همیشه با اطمینان میتونید نسخه Rust رو به آخرین نسخه Stable به روز رسانی کنید; که شامل فیچر های جدید، باگ های کمتر و بهبود زمان کامپایل میشه.
در کنار نسخه Stable همچنین نسخه های Beta و Nightly این زبان هم موجود هستند. بیشتر جامعه توسعه دهندگان Rust در درجه اول از نسخه Stable استفاده میکنند ، اما اگر میخواهید ویژگی های جدید آزمایشی را امتحان کنید، میتونید نسخه های Beta و Nightly رو بررسی کنید. این نسخه های مختلف در چرخه بسیار جالبی توسعه، نگهداری و منتشر میشند.
هر وقت فیچر جدیدی به Rust اضافه بشه، یک کامیت جدید به برنچ master پروژه اضافه میشه... هر شب یک نسخه Nightly جدید از Rust شکل میگیره که روز بعدش، اون نسخه منتشر میشه. و این پروسه توسط زیرساخت های انتشار Rust به شکل اتوماتیک انجام میشه. پس هر شب یک چنین حالتی رو داریم:
هر ۶ هفته یک نسخه جدید منتشر میشه.. پس در این مرحله برنچ master نسخه Nightly به ریپازیتوری نسخه Beta منتقل میشه. پس تا اینجا دو نسخه داریم:
اکثر توسعه دهندگاه Rust از نسخه Beta به شکل فعال استفاده نمیکنند، اما عده ای هم با تست این نسخه به این اکوسیستم کمک میکنند تا رگرسیون (پسرفت) های احتمالی رو پیدا کنند. در این حین، هر شب هنوز یک نسخه جدید از Nightly داره آماده میشه:
اگر در پروسه توسعه پسرفت، باگ یا مشکلی احتمالی پیدا بشه.. مشکل حل میشه و راه حل اون به روی برنچ master اعمال میشه، پس این باگ در نسخه Nightly برطرف میشه.. بعد همین راه حل به برنچ Beta بازگشت داده میشه و نسخه Beta جدیدی شکل میگیره:
۶ هفته بعد از بهوجود اومدن اولین نسخه Beta ، حالا زمان انتشار نسخه Stable هست. در این زمان از آخرین نسخه Beta ی که موجود هست، نسخه Stable شکل میگیره:
از اونجا که ۶ هفته تموم شده، حالا نیاز به نسخه Beta جدید داریم. پس نسخه جدید Beta دوباره از نسخه Nightly شکل میگیره:
به این چرخه Train Model یا مدل قطار میگند. چون هر ۶ هفته یه نسخه جدید ایستگاه رو ترک میکنه اما هنوز باید کانال Beta رو طی کنه تا به یک نسخه Stable تبدیل بشه.
در نوشته بعد با مفاهیم متداول برنامه نویسی در زبان Rust آشنا میشیم.