نحوه راه اندازی گوشی های هوشمند و رایانه های شخصی. پرتال اطلاعاتی
  • خانه
  • اهن
  • زبان برنامه نویسی Rust. مروری بر زبان برنامه نویسی Rust

زبان برنامه نویسی Rust. مروری بر زبان برنامه نویسی Rust

در سال 2013، موزیلا به همراه سامسونگ توسعه یک موتور مرورگر وب جدید به نام Servo را اعلام کردند. این به طور خاص برای پردازنده های چند هسته ای دستگاه های تلفن همراه ایجاد شده است، می تواند وظایف را به رشته های موازی تقسیم کند و زمان بارگذاری صفحات وب را تا حد زیادی کاهش دهد. Servo به طور کامل به زبان برنامه نویسی Rust نوشته شده است، که موزیلا خود آن را برای نوشتن برنامه های تلفن همراه توسعه داده است.

در مورد زبان

Rust یک زبان برنامه نویسی رویه ای است که از انواع سبک های کدنویسی پشتیبانی می کند. توسعه دهنده Graydon Hoare در سال 2006 شروع به ایجاد این زبان کرد و سه سال بعد موزیلا به پروژه پیوست. در سال 2010، Rust در کنفرانس موزیلا Summit ارائه شد. در همان سال، توسعه به یک کامپایلر نوشته شده در Rust منتقل شد. کامپایلر از سیستم تحلیل و تبدیل برنامه جهانی LLVM به عنوان پایگاه داده استفاده کرد.

اولین نسخه پایدار این زبان در سال 2015 منتشر شد. پس از انتشار نسخه آلفا، Rust دستخوش تغییراتی شد - فقط ویژگی های آماده در داخل کامپایلر باقی مانده بود که تغییر نمی کند. بقیه موارد به بخش تجربی منتقل شد.

در قلب این زبان، گریدون هور مفاهیمی از قبیل:

  • ایمنی. Rust شامل تعدادی محدودیت برنامه نویس است که به طور پیش فرض فعال هستند. برای غیرفعال کردن آنها، برچسب "ناامن" در بلوک ها و توابع مورد نیاز است.
  • سرعت. این زبان از نظر سرعت با یک زبان برنامه نویسی دیگر، C++ قابل مقایسه است که مزایای واضحی را برای برنامه نویس فراهم می کند.
  • موازی سازی. این سیستم می تواند چندین محاسبات را به طور همزمان انجام دهد و در عین حال می توانند با یکدیگر تعامل داشته باشند.
  • اختصار. اولین کلمات کلیدی در Rust به پنج کاراکتر محدود می شد. اما بعداً این محدودیت برداشته شد.

نمونه ای از اولین کدها در Rust

با این حال، Rust خالی از اشکال نیست که بارزترین آنها عبارتند از:

  • افزونگی کد.
  • کمبود ادبیات برای یادگیری زبان.
  • وضوح در وارد کردن پارامترهای کامپایل. این همیشه برای برنامه نویسان با تجربه مناسب نیست، زیرا سایر زبان ها قوانین مشابهی ندارند.

با این حال، این زبان به طور مرتب مدرن و گسترش می یابد: به روز رسانی های آن هر 6 هفته منتشر می شود.

مقایسه Rust با C++

سازندگان Rust آن را جانشین C++ می‌دانند که در اوایل دهه 1980 زمانی که توسعه‌دهنده چندین پیشرفت را در زبان C ارائه کرد، ظاهر شد. بنابراین، ارزش مقایسه زبان جوان و هنوز در حال تغییر را با زبان آزمایش‌شده زمان دارد.

  • دسترسی به حافظه از راه دور در C++، حذف یک متغیر می تواند مشکلات زیادی ایجاد کند. چنین عوارضی در Rust امکان پذیر نیست، زیرا دستوراتی برای حذف حافظه ندارد. کامپایلر decendant گزارش می دهد که کدی که نوشته اید حاوی خطا است و کامپایلر C++ نتیجه را بدون مقادیر حذف شده و حتی بدون گزارش مشکل، خروجی می دهد.
  • نقطه ویرگول. افزودن یک نقطه ویرگول اضافی به کد شما باعث ایجاد خطا در C++ می شود، در حالی که در Rust بدنه حلقه در بریس های فرفری محصور شده است.
  • کد ناامن Rust دارای یک برچسب "ناامن" است که کد اصلی را از کد ناامن جدا می کند. در آینده، هنگام بررسی کد، این امکان را به شما می دهد تا جستجوی آسیب پذیری ها را محدود کنید.

فایرفاکس در C++ پیاده‌سازی شد: این زبان هوس‌باز نیازمند توجه بیشتر به جزئیات بود. در غیر این صورت، خطاها به آسیب پذیری های جدی تبدیل می شوند. Rust برای حل این مشکل طراحی شده است.

چشم انداز

در رتبه بندی RedMonk برای سه ماهه سوم سال 2018، زبان برنامه نویسی موزیلا به طور مداوم در رتبه 23 قرار دارد. کارشناسان معتقدند وضعیت او در خطر بهبود نیست. با وجود این، در آگوست 2018 سازندگان Rust 1.28 به روز شده را منتشر کردند.

پس از انتشار Rust در سال 2015، با توجه به Stack Overflow، 74 درصد از توسعه دهندگان می خواستند با آن آشنا شوند. با این حال، در حال حاضر در سال 2016، به رتبه اول منتقل شد: 79٪ از کاربران Rust را به عنوان زبان برنامه نویسی مورد علاقه خود نام بردند و تمایل خود را برای ادامه کار با آن ابراز کردند. Rust مقام اول را در این پارامتر در سال 2018 به خود اختصاص داد.

Stack Overflow یک سیستم پرسش و پاسخ برنامه نویسی محبوب است که در سال 2008 توسعه یافته است.

محبوبیت Rust توسط تعداد شرکت هایی که از آن در توسعه خود استفاده می کنند تأیید می شود. در حال حاضر این فهرست شامل 105 سازمان است.

بنابراین، ما می خواهیم یک پسر تولد اخیر را به شما معرفی کنیم (او در 15 می 2016 یک ساله شد) - Rust. این یک زبان برنامه نویسی جهانی است که توسط موزیلا توسعه یافته است که سه اصل اصلی آن عبارتند از: سرعت، امنیت و ارگونومی. خود سازندگان آن را یکی از محتمل ترین جانشینان C/C++ می دانند. طبق یک نظرسنجی در StackOverflow، امروزه Rust محبوب ترین زبان در بین توسعه دهندگان است. بنابراین، بیایید نگاهی دقیق تر به چیستی آن بیندازیم.

زنگ برای یک مبتدی

من نمی خواهم کسی را فریب دهم، بنابراین در اینجا یک بیانیه مسئولانه وجود دارد: یادگیری زنگ بسیار دشوار است. اولاً این به خاطر جوانی زبان و در نتیجه کم بودن ادبیات است. ثانیاً، ممکن است یادگیری آن برای افرادی که از برنامه نویسی دور هستند، آسان تر از افرادی باشد که با زبان های دیگر آشنا هستند. بنابراین، به عنوان مثال، یک متخصص فناوری اطلاعات آماده از نیاز به تجویز کوچکترین عملیات بسیار آزرده می شود و عدم وجود ارث در زبان به سادگی او را گیج می کند.

با این حال، Rust به سرعت در حال توسعه است (یک نسخه جدید هر 6 هفته یکبار منتشر می شود)، جامعه در حال رشد است و یافتن اطلاعات در اینترنت دیگر دشوار نیست.

روش مطالعه

تقریباً همه چیزهایی که نیاز دارید را می توانید در وب سایت رسمی پیدا کنید. علاوه بر این، جامعه پیروان Rust بسیار بزرگ و دوستانه است، بنابراین همیشه می توانید برای مشاوره به IRC (بخش روسی وجود دارد) و انجمن رسمی مراجعه کنید. علاوه بر این، کتاب ها، از جمله کتاب های الکترونیکی، کم کم ظاهر شدند. ارزیابی کیفیت آنها هنوز دشوار است، اما این یک واقعیت است.

برای کسانی که مرحله اولیه آشنایی را پشت سر گذاشته‌اند، می‌توانند مطالب مفید زیادی از جمله RFC و commit در GiHub پیدا کنند. علاوه بر این، می توانید شخصاً شرکت کنید یا حداقل پخش اینترنتی یکی از کنفرانس های Rust را که برای نیمه دوم سال برنامه ریزی شده است تماشا کنید. این هم تقویم:

  • کنفرانس RustConf از 9 تا 10 سپتامبر در پورتلند، ایالات متحده؛
  • 17 سپتامبر، کنفرانس جوامع اروپایی RustFest در برلین، آلمان؛
  • 27 اکتبر کنفرانس Rust Belt Rust در پیتسبورگ، ایالات متحده;

خوب، برای ملاقات با کسانی که Rust را فراخوان خود می دانند، و در عین حال از آنها تمام خرد خود را بخواهید، می توانید با برگزارکنندگان و شرکت کنندگان جلسات طرفداران زبان در مسکو تماس بگیرید.

ویژگی های خاص

با کمی تکرار از آنچه قبلاً گفته شد، مزایا و معایب اصلی زبان Rust را برجسته خواهیم کرد.

طرفداران:

  • کار ایمن با حافظه؛
  • عملکرد بالا؛
  • نوع داده جبری؛
  • قابل پیش بینی بودن تدوین؛

معایب:

  • مقداری افزونگی کد؛
  • شدت بالای توسعه زبان و در نتیجه عدم وجود ادبیات مناسب مناسب برای مطالعه؛
  • نیاز به مشخص کردن واضح و بدون ابهام پارامترها برای کامپایل.

در واقع، به سرعت به تفاوت‌ها عادت می‌کنید، مانند جایگزینی وراثت با توانایی‌ها. به محض اینکه چشمان شما به آن عادت می کند و دستان شما به آن عادت می کنند، Rust به یک زبان کاملاً کاربردی تبدیل می شود، ساده تر و کاربردی تر از C++، اما از نظر "زیبایی" نسبت به بسیاری از زبان های برنامه نویسی دیگر پایین تر است. در واقع تفاوت اصلی Rust با رقبا و پیشینیانش سرعت و امنیت است.

تقاضا

امروزه Rust در بین توسعه دهندگان بازی، گرافیک و سیستم عامل محبوب است. با این حال، به دلایل واضح، تعداد مکان‌های ثابتی که در آن متخصصان بسیار تخصصی Rust مورد نیاز هستند، در جهان بسیار کم است و حتی در روسیه بیشتر از آن. با این حال، هنوز هیچ نشانه‌ای وجود ندارد که این زبان در فراموشی فرو خواهد رفت؛ این بیشتر شبیه تسخیر سیستماتیک جهان است. این بدان معنی است که مهارت های خوب در استفاده از Rust در آینده به شما کمک می کند تا شغلی با درآمد خوب و جالب در کشور ما و خارج از کشور پیدا کنید.

هنوز در تقاضا: حرفه "".

زنگیک زبان برنامه نویسی آزمایشی جدید است که توسط موزیلا توسعه یافته است. این زبان کامپایل شده و چند پارادایم است و به عنوان جایگزینی برای C/C++ قرار گرفته است، که به خودی خود جالب است، زیرا حتی رقبای زیادی برای رقابت وجود ندارد. می توانید والتر برایت D یا گوگل گو را به خاطر بسپارید.
Rust از برنامه نویسی عملکردی، موازی، رویه ای و شی گرا پشتیبانی می کند. تقریباً کل طیف پارادایم هایی که واقعاً در برنامه نویسی کاربردی استفاده می شوند.

هدف من ترجمه مستندات نیست (علاوه بر این، بسیار کمیاب است و دائماً در حال تغییر است، زیرا هنوز انتشار رسمی این زبان وجود نداشته است)، در عوض می‌خواهم جالب‌ترین ویژگی‌های زبان را برجسته کنم. اطلاعات هم از اسناد رسمی و هم از ذکر بسیار اندک این زبان در اینترنت جمع آوری شده است.

اولین برداشت

نحو زبان به سبک سنتی C ساخته شده است (که خبر خوبی است، زیرا این در حال حاضر یک استاندارد واقعی است). طبیعتاً خطاهای طراحی معروف C/C++ در نظر گرفته شده است.
یک Hello World سنتی به این شکل است:
استفاده از std; fn main(args: ) ( std::io::println("سلام جهان از " + args + "!")؛ )

یک مثال کمی پیچیده تر - تابع محاسبه فاکتوریل:

Fn fac(n: int) -> int (بگذارید نتیجه = 1، i = 1؛ در حالی که i<= n { result *= i; i += 1; } ret result; }

همانطور که از مثال می بینید، توابع به سبک "عملکردی" اعلان شده اند (این سبک نسبت به "int fac(int n)" سنتی مزایایی دارد). می بینیم استنتاج نوع خودکار(کلید واژه اجازه دهید)، بدون پرانتز در آرگومان while (همان Go). نکته دیگری که بلافاصله توجه شما را به خود جلب می کند فشرده بودن کلمات کلیدی است. سازندگان Rust واقعاً تمام کلمات کلیدی را تا حد امکان کوتاه نگه داشته اند و صادقانه بگویم، من آن را دوست دارم.

ویژگی های نحوی کوچک اما جالب

  • می توانید زیرخط ها را در ثابت های عددی وارد کنید. این یک ویژگی مفید است؛ این ویژگی اکنون به بسیاری از زبان های جدید اضافه می شود.
    0xffff_ffff_ffff_ffff_ffff_ffff
  • ثابت های دودویی البته، یک برنامه نویس واقعی باید در سر خود bin را به هگز تبدیل کند، اما این روش راحت تر است! 0b1111_1111_1001_0000
  • بدنه هر عبارت (حتی آنهایی که از یک عبارت واحد تشکیل شده اند) باید در پرانتزهای مجعد محصور شوند. به عنوان مثال، در C می توانید if(x>0) foo(); ، در Rust باید بریس های فرفری را در اطراف foo() قرار دهید.
  • اما آرگومان های if، while و عملگرهای مشابه نیازی به داخل پرانتز ندارند
  • در بسیاری از موارد، بلوک های کد را می توان به عنوان عبارات در نظر گرفت. به طور خاص، موارد زیر ممکن است:
    اجازه دهید x = if the_stars_align() (4) else if something_else() (3) else (0);
  • نحو اعلان تابع - ابتدا کلمه کلیدی fn، سپس لیستی از آرگومان ها، نوع آرگومان بعد از نام نشان داده می شود، سپس، اگر تابع مقداری را برمی گرداند، یک فلش "->" و نوع مقدار بازگشتی را نشان می دهد.
  • متغیرها به همین ترتیب اعلان می شوند: کلمه کلیدی let، نام متغیر، بعد از متغیر می توانید نوع را از طریق دو نقطه مشخص کنید و سپس مقدار اولیه را تعیین کنید.
    اجازه count: int = 5;
  • به طور پیش فرض، همه متغیرها تغییر ناپذیر هستند. کلمه کلیدی mutable برای اعلام متغیرهای قابل تغییر استفاده می شود.
  • نام انواع پایه فشرده ترین از همه چیزهایی است که من با آنها برخورد کرده ام: i8، i16، i32، i64، u8، u16، u32، u64، f32، f64
  • همانطور که در بالا ذکر شد، استنتاج نوع خودکار پشتیبانی می شود
این زبان دارای ابزارهای اشکال زدایی برنامه داخلی است:
کلمه کلیدی شکستروند فعلی را پایان می دهد
کلمه کلیدی ورود به سیستمخروجی هر عبارت زبانی را به log می دهد (مثلاً به stderr)
کلمه کلیدی ادعا کردنعبارت را بررسی می کند و در صورت نادرست بودن، روند فعلی را خاتمه می دهد
کلمه کلیدی توجه داشته باشیدبه شما امکان می دهد در صورت پایان غیرعادی فرآیند، اطلاعات اضافی را نمایش دهید.

انواع داده ها

Rust مانند Go پشتیبانی می کند تایپ سازه ای(اگرچه، به گفته نویسندگان، زبان ها به طور مستقل توسعه یافته اند، بنابراین این تأثیر پیشینیان رایج آنها - الف، لیمبو و غیره) است. تایپ ساختاری چیست؟ به عنوان مثال، شما ساختاری دارید که در برخی از فایل ها اعلام شده است (یا در اصطلاح Rust، یک "رکورد")
type point = (x: float, y: float);
شما می توانید دسته ای از متغیرها و توابع را با انواع آرگومان "point" اعلام کنید. سپس، در جای دیگری، می توانید ساختار دیگری را مانند
MySuperPoint = (x: float, y: float) را تایپ کنید.
و متغیرهایی از این نوع با متغیرهای نوع point سازگاری کامل خواهند داشت.

در مقابل، تایپ اسمی پذیرفته شده در C، C++، C# و جاوا اجازه چنین ساختارهایی را نمی دهد. با تایپ اسمی، هر ساختار یک نوع منحصر به فرد است که به طور پیش فرض با انواع دیگر ناسازگار است.

به سازه‌های Rust "Record" می‌گویند. چندین تاپل نیز وجود دارد - اینها همان رکوردها هستند، اما با فیلدهای بی نام. عناصر یک تاپل، بر خلاف عناصر یک رکورد، نمی توانند تغییرپذیر باشند.

بردارهایی وجود دارد - از جهاتی شبیه به آرایه های معمولی و از جهاتی شبیه به نوع std:: vector از stl است. هنگام مقداردهی اولیه با یک لیست، از براکت های مربع استفاده می شود، نه از براکت های فرفری مانند C/C++

اجازه دهید myvec = ;

با این حال، یک بردار یک ساختار داده پویا است؛ به ویژه، بردارها از الحاق پشتیبانی می کنند.

اجازه دهید v: قابل تغییر = ; v += ;

قالب ها وجود دارد. نحو آنها کاملا منطقی است، بدون درهم ریختگی "الگو" از C++. الگوهای تابع و نوع داده پشتیبانی می شوند.

Fn for_rev (v: [T]، act: block(T)) (بگذارید i = std::vec::len(v؛ در حالی که i > 0u (i -= 1u؛ act(v[i]); )) تایپ کنید دایره ای_باف = (شروع: uint، پایان: uint، buf: );

زبان به اصطلاح پشتیبانی می کند برچسب ها. این چیزی نیست جز یک اتحاد از C، با یک فیلد اضافی - کد نوع مورد استفاده (یعنی چیزی مشترک بین یک اتحادیه و یک شمارش). یا، از دیدگاه نظری، یک نوع داده جبری.

شکل برچسب (دایره (نقطه، شناور)؛ مستطیل (نقطه، نقطه)؛ )

در ساده ترین حالت، یک تگ با یک شمارش یکسان است:

تگ حیوان ( سگ؛ گربه؛ ) let a: animal = سگ; الف = گربه؛
در موارد پیچیده تر، هر عنصر "شمارش" یک ساختار مستقل است که "سازنده" خود را دارد.
مثال جالب دیگر یک ساختار بازگشتی است که برای تعریف یک شی از نوع "list" استفاده می شود:
لیست برچسب ( صفر؛ منفی (T، @list ) ) let a: list = منفی (10، @cons (12، @nil));
برچسب ها می توانند در عبارات تطبیق الگو شرکت کنند که می تواند بسیار پیچیده باشد.
alt x (cons(a, @cons(b, _)) (process_pair(a,b); ) cons(10, _) (process_ten();) _ ( شکست؛ ))

تطبیق الگو

برای شروع، می توانیم الگوی تطبیق را به عنوان یک سوئیچ بهبود یافته در نظر بگیریم. از کلمه کلیدی alt استفاده می شود، به دنبال آن عبارت مورد تجزیه و تحلیل قرار می گیرد و سپس در بدنه عبارت - الگوها و اقدامات در صورت مطابقت الگوها استفاده می شود.
alt my_number ( 0 ( std::io::println("صفر"); ) 1 | 2 ( std::io::println("یک یا دو"); ) 3 تا 10 ( std::io::println ("سه تا ده")؛ ) _ ( std::io::println("چیز دیگری")؛ ) )
به عنوان "الگوها" می توانید نه تنها از ثابت ها (مانند C)، بلکه از عبارات پیچیده تر - متغیرها، تاپل ها، محدوده ها، انواع، نگهدارنده ها ("_") استفاده کنید. شما می توانید شرایط اضافی را با استفاده از دستور when بلافاصله بعد از الگو مشخص کنید. یک نوع خاص از عملگر برای تطبیق نوع وجود دارد. این امکان پذیر است زیرا زبان دارای یک نوع مختلف جهانی است هر، که اشیاء آن می توانند حاوی مقادیری از هر نوع باشند.

اشاره گرهاعلاوه بر نشانگرهای معمولی "C"، Rust از نشانگرهای "هوشمند" ویژه با شمارش ارجاع داخلی - مشترک (جعبه های مشترک) و منحصر به فرد (جعبه های منحصر به فرد) پشتیبانی می کند. آنها تا حدودی شبیه به shared_ptr و unique_ptr از C++ هستند. آنها نحو خاص خود را دارند: @ برای اشتراک گذاری و ~ برای منحصر به فرد. برای اشاره گرهای منحصر به فرد، به جای کپی کردن، یک عملیات ویژه وجود دارد - جابجایی:
اجازه دهید x = ~ 10; اجازه دهید y<- x;
پس از چنین حرکتی، نشانگر x از مقدار اولیه خارج می شود.

بسته شدن، برنامه های جزئی، تکرار کننده ها

اینجاست که برنامه نویسی تابعی شروع می شود. Rust به طور کامل از مفهوم توابع درجه بالاتر پشتیبانی می کند - یعنی توابعی که می توانند توابع دیگر را به عنوان آرگومان بگیرند و آنها را برگردانند.

1. کلمه کلیدی لامبدابرای اعلام یک تابع تودرتو یا نوع داده عملکردی استفاده می شود.

Fn make_plus_function(x: int) -> lambda(int) -> int ( lambda(y: int) -> int (x + y) ) اجازه دهید plus_two = make_plus_function(2); عنوان plus_two(3) == 5;

در این مثال، ما یک تابع make_plus_function داریم که یک آرگومان "x" از نوع int را می گیرد و تابعی از نوع "int->int" را برمی گرداند (لامبدا در اینجا کلمه کلیدی است). بدن تابع دقیقا همین عملکرد را توصیف می کند. فقدان اپراتور "بازگشت" کمی گیج کننده است، اما این یک چیز رایج برای FP ها است.

2. کلمه کلیدی مسدود کردنبرای اعلام یک نوع تابعی استفاده می شود - یک آرگومان تابع، که می تواند با چیزی شبیه به یک بلوک کد معمولی جایگزین شود.
fn map_int(f: block(int) -> int, vec: ) -> ( اجازه دهید نتیجه = ; برای i در vec (نتیجه += ; ) ret نتیجه؛ ) map_int((|x| x + 1 ), );

در اینجا ما تابعی داریم که ورودی آن یک بلوک است - اساساً یک تابع لامبدا از نوع "int->int" و یک بردار از نوع int (در ادامه در مورد نحو بردارها بیشتر خواهد شد). خود "بلوک" در کد فراخوانی با استفاده از یک نحو غیرمعمول (|x| x + 1) نوشته شده است. من شخصاً لامبدا را در سی شارپ ترجیح می دهم، نماد | به طور مداوم به عنوان OR بیتی درک می شود (که اتفاقاً در Rust نیز وجود دارد، مانند همه عملیات های قدیمی مبتنی بر C).

3. کاربرد جزئی ایجاد تابعی بر اساس تابع دیگر با آرگومان های بیشتر با مشخص کردن مقادیر برخی از آرگومان های آن تابع دیگر است. کلمه کلیدی مورد استفاده برای این است بستنو یک کاراکتر متغیر "_":

بگذارید daynum = bind std::vec:: position(_، ["mo"، "tu"، "we"، "do"، "fr"، "sa"، "su"])

برای روشن تر شدن موضوع، فوراً می گویم که این کار را می توان در C معمولی با ایجاد یک لفاف ساده انجام داد، چیزی شبیه به این:
const char* daynum (int i) ( const char *s =("mo"، "tu"، "we"، "do"، "fr"، "sa"، "su"); return s[i]; )

اما کاربرد جزئی یک سبک عملکردی است نه رویه ای (به هر حال، از مثال ارائه شده مشخص نیست که چگونه یک برنامه جزئی برای دریافت یک تابع بدون آرگومان انجام دهیم)

مثال دیگر: تابع add با دو آرگومان int اعلان می شود که int را برمی گرداند. سپس نوع تابعی single_param_fn اعلام می شود که دارای یک آرگومان int است و int را برمی گرداند. با استفاده از bind، دو شیء تابع add4 و add5 اعلام می‌شوند که بر اساس تابع add ساخته شده‌اند که تا حدی آرگومان‌های مشخص شده دارد.

Fn add(x: int, y: int) -> int ( ret x + y; ) type single_param_fn = fn(int) -> int; اجازه دهید add4: single_param_fn = bind add(4, _); اجازه دهید add5: single_param_fn = bind add(_, 5);

اشیاء تابع را می توان به همان روشی که توابع منظم فراخوانی کرد.
اظهار (add(4,5) == add4(5)); اظهار (add(4,5) == add5(4));

4. توابع و محمولات محض
توابع خالص، توابعی هستند که عوارض جانبی ندارند (از جمله آنهایی که به جز توابع خالص، هیچ عملکرد دیگری را فراخوانی نمی کنند). چنین توابعی با کلمه کلیدی خالص شناسایی می شوند.
pure fn lt_42 (x: int) -> bool ( ret (x< 42); }
گزاره ها توابع خالصی هستند که نوع bool را برمی گرداند. چنین توابعی را می توان در سیستم typestate استفاده کرد (به زیر مراجعه کنید)، یعنی در مرحله کامپایل برای بررسی های مختلف استاتیک فراخوانی می شود.

ماکروهای نحوی
یک ویژگی برنامه ریزی شده، اما بسیار مفید. هنوز در Rust در مراحل اولیه توسعه است.
std::io::println(#fmt("%s %d است"، "جواب"، 42));
عبارتی شبیه به C's printf، اما در زمان کامپایل اجرا می شود (بر این اساس، تمام خطاهای آرگومان در مرحله کامپایل شناسایی می شوند). متأسفانه، مواد بسیار کمی در مورد ماکروهای نحوی وجود دارد، و خود آنها در حال توسعه هستند، اما این امید وجود دارد که چیزی مانند ماکروهای Nemerle به نتیجه برسد.
به هر حال، بر خلاف Nemerle، من تصمیم به برجسته کردن ماکروها از نظر نحوی با استفاده از نماد # را بسیار هوشمندانه می‌دانم: ماکرو موجودی است که بسیار متفاوت از یک تابع است، و فکر می‌کنم در نگاه اول مهم است که ببینیم کجا در کجاست. توابع کد فراخوانی می شوند و کجا - ماکروها.

ویژگی های

مفهومی شبیه به ویژگی های C# (و حتی با نحو مشابه). تشکر ویژه از توسعه دهندگان برای این. همانطور که انتظار دارید، ویژگی ها اطلاعات متا را به موجودی که حاشیه نویسی می کنند اضافه می کنند.
# fn register_win_service() ( /* ... */ )
نوع دیگری از نحو صفت اختراع شده است - همان خط، اما با یک نقطه ویرگول در انتها، زمینه فعلی را حاشیه نویسی می کند. یعنی چه چیزی با نزدیکترین بریس های فرفری که چنین ویژگی را در بر می گیرد مطابقت دارد.
fn register_win_service() (#; /* ... */)

محاسبات موازی

شاید یکی از جالب ترین بخش های زبان. در ضمن فعلا در آموزش اصلا توضیح داده نشده :)
یک برنامه Rust از یک "درخت وظیفه" تشکیل شده است. هر وظیفه دارای یک تابع ورودی، پشته خاص خود، ابزار تعامل با سایر وظایف است - کانال هایی برای اطلاعات خروجی و پورت هایی برای اطلاعات ورودی، و مالک برخی از اشیاء در پشته پویا است.
چندین کار Rust می تواند در یک فرآیند سیستم عامل وجود داشته باشد. وظایف Rust "سبک" هستند: هر کار نسبت به فرآیند OS حافظه کمتری مصرف می کند و جابجایی بین آنها سریعتر از جابجایی بین فرآیندهای OS است (در اینجا احتمالاً منظور ما "threads" است).

یک کار حداقل از یک تابع بدون آرگومان تشکیل شده است. کار با استفاده از تابع spawn راه اندازی می شود. هر وظیفه می تواند کانال هایی داشته باشد که از طریق آنها اطلاعات را به وظایف دیگر منتقل می کند. کانال یک نوع قالب خاص است که با نوع داده کانال پارامتر می شود. به عنوان مثال، chan کانالی برای انتقال بایت های بدون علامت است.
برای ارسال به کانال از تابع send استفاده کنید که اولین آرگومان آن کانال و دومین آرگومان مقداری است که باید ارسال شود. این تابع در واقع مقدار را در بافر داخلی کانال قرار می دهد.
پورت ها برای دریافت داده ها استفاده می شوند. پورت یک نوع پورت عمومی است که با نوع داده پورت پارامتر می شود: پورت پورتی برای دریافت بایت های بدون علامت است.
برای خواندن از پورت ها از تابع recv استفاده کنید که آرگومان آن پورت و مقدار بازگشتی داده های پورت است. خواندن کار را مسدود می کند، یعنی. اگر پورت خالی باشد، وظیفه وارد حالت انتظار می شود تا زمانی که وظیفه دیگری داده ها را به کانال مرتبط با پورت ارسال کند.
ارتباط کانال ها با پورت ها بسیار ساده است - با مقداردهی اولیه کانال با یک پورت با استفاده از کلمه کلیدی chan:
let reqport = port();
let reqchan = chan(reqport);
چندین کانال را می توان به یک پورت متصل کرد، اما نه برعکس - یک کانال را نمی توان همزمان به چندین پورت متصل کرد.

حالت تایپ

من یک ترجمه عمومی پذیرفته شده به روسی از مفهوم "typestate" پیدا نکردم، بنابراین آن را "حالات نوع" می نامم. ماهیت این ویژگی این است که علاوه بر بررسی نوع معمولی که در تایپ استاتیک اتخاذ می شود، بررسی های متنی اضافی در مرحله کامپایل امکان پذیر است.
به هر شکلی، حالت های نوع برای همه برنامه نویسان آشنا هستند - طبق پیام های کامپایلر، "متغیر بدون مقداردهی اولیه استفاده می شود." کامپایلر مکان هایی را شناسایی می کند که متغیری که هرگز در آن نوشته نشده است خوانده می شود و اخطاری صادر می کند. در شکل کلی تر، این ایده به این صورت است: هر شی دارای مجموعه ای از حالت هایی است که می تواند داشته باشد. هر حالت عملیات معتبر و نامعتبر را برای آن شی تعریف می کند. و کامپایلر می تواند بررسی کند که آیا یک عملیات خاص روی یک شی در یک مکان خاص در برنامه مجاز است یا خیر. مهم است که این بررسی ها در زمان تدوین انجام شود.

به عنوان مثال، اگر یک شی از نوع "file" داشته باشیم، می تواند حالت "بسته" و "باز" ​​داشته باشد. و اگر فایل بسته باشد، عملیات خواندن از یک فایل مجاز نیست. در زبان‌های مدرن، معمولاً تابع read یا یک استثنا ایجاد می‌کند یا یک کد خطا برمی‌گرداند. یک سیستم حالت نوع می‌تواند چنین خطایی را در زمان کامپایل تشخیص دهد - همانطور که کامپایلر تشخیص می‌دهد که یک عملیات خواندن روی یک متغیر قبل از هر عملیات نوشتن احتمالی رخ می‌دهد، می‌تواند تعیین کند که روش "خواندن" در حالت "فایل باز" معتبر است. ، قبل از متد "Open" فراخوانی می شود که شی را به این حالت منتقل می کند.

Rust دارای مفهوم "مقدمات" است - عملکردهای ویژه ای که هیچ عوارض جانبی ندارند و یک نوع bool را برمی گرداند. چنین توابعی می تواند توسط کامپایلر برای فراخوانی در مرحله کامپایل به منظور بررسی ایستا شرایط خاص استفاده شود.

محدودیت ها بررسی های خاصی هستند که می توانند در زمان کامپایل انجام شوند. برای این کار از کلمه کلیدی چک استفاده می شود.
fn خالص is_less_than(int a, int b) -< bool { ret a < b; } fn test() { let x: int = 10; let y: int = 20; check is_less_than(x,y); }
محمول ها را می توان به این ترتیب روی پارامترهای ورودی توابع "آویزان" کرد:
تست fn(int x, int y): is_less_than(x,y) (...)

اطلاعات بسیار کمی در مورد typestate وجود دارد، بنابراین بسیاری از جنبه ها هنوز نامشخص هستند، اما به هر حال مفهوم آن جالب است.

همین. کاملاً ممکن است که من هنوز نکات جالبی را از دست داده باشم، اما مقاله قبلاً پف کرده بود. در صورت تمایل، اکنون می توانید یک کامپایلر Rust بسازید و سعی کنید با مثال های مختلف بازی کنید. اطلاعات مونتاژ در ارائه شده است


مقاله «نقد زبان رست و چرا C/C++ هرگز نمی میرد» را خیلی دوست داشتیم. ما به نویسنده پیشنهاد کردیم که مقاله را به انگلیسی ترجمه کرده و در وبلاگ خود نیز منتشر کنیم. او موافقت کرد و ما خوشحالیم که این مقاله را به روسی و انگلیسی ارائه می کنیم. اصل مقاله قرار دارد.

مقاله اصلی ارسال شده است (متن به زبان روسی). این مقاله با موافقت نویسنده در وبلاگ ما منتشر شد.

نکته: در ادامه این فرض را مطرح می کنم که Rust تلاشی برای ساخت زبانی سریع و ایمن است. به هر حال، بچه های موزیلا آن را به عنوان یک ابزار توسعه موتور مرورگر ساخته اند. اگر این فقط یک زبان امن دیگر است، پس ما چیز عجیبی دریافت می کنیم. در حال حاضر یک دوجین زبان امن مختلف وجود دارد، هر کسی چیزی را به میل خود پیدا می کند. و اگر هدف جایگزینی ++C نیست، پس (1) چرا یک زیرمجموعه ناامن در زبان ساخته شده است؟ (2) چرا لازم بود جریانهای سبک وزن را از زبان حذف کنیم؟ راحت نیست؟ به عبارت دیگر، در این مورد، آنچه در حال رخ دادن است اصلاً معنی ندارد.

اگر در حال خواندن انجمن linux.org.ru هستید، توجه می کنم که این لیستی از 10 دلیل کاملاً فنی برای دوست نداشتن Rust نیست که در این تاپیک مورد بحث قرار گرفت. همانطور که توسط یک بحث در اسکایپ با نشان داده شده است رفیق عزیز @sum3rman، بیش از یک نظر در مورد اینکه این دلایل چقدر "فنی" باید در نظر گرفته شوند وجود دارد. به طور کلی، من یک لیست مزخرف تهیه کردم، اما احتمالاً همچنان خطر ذکر برخی از جالب ترین نکات آن را دارم. در واقع، دلایل ساده و غیر فنی زیادی در اینجا وجود دارد.

این واقعیت که C/C++ در آینده قابل پیش‌بینی به جایی نمی‌رسد برای هر فرد هوشیار روشن است. هیچ کس تقریباً همه برنامه های دسکتاپ، هسته های سیستم عامل، کامپایلرها، موتورهای بازی و مرورگر، ماشین های مجازی، پایگاه های داده، آرشیوها، کدک های صوتی و تصویری، هزاران کتابخانه دیگر مبتنی بر C و غیره را بازنویسی نمی کند. این کدهای بسیار سریع، اشکال زدایی شده و تست شده بسیار زیاد است. بازنویسی آن بسیار بسیار پرهزینه، مخاطره آمیز است، و صادقانه بگوییم، تنها در هشیاری تحریف شده تنها سرسخت ترین طرفداران Rust منطقی است. تقاضا برای برنامه نویسان C/C++ برای مدت بسیار طولانی زیاد بوده و خواهد بود.

خوب، در مورد استفاده از Rust هنگام نوشتن کد جدید چطور؟

به یاد داشته باشیم که این اولین تلاش برای ایجاد یک C/C++ "صحیح تر" نیست. به عنوان مثال، زبان D را در نظر بگیریم. این زبان در سال 2001 ظاهر شد، یک زبان بسیار خوب. هیچ جای خالی، هیچ ابزار توسعه عادی، هیچ داستان موفقیت برجسته ای وجود ندارد. پروژه OpenMW ابتدا با D نوشته شده بود و سپس ناگهان تصمیم گرفتند که آن را به طور کامل در C++ بازنویسی کنند. همانطور که توسعه دهندگان اعتراف می کنند، آنها نامه های زیادی به سبک "پروژه عالی، ما خوشحال می شویم که در آن مشارکت کنیم، اما ما این D احمقانه را نمی دانیم و نمی خواهیم بدانیم." ویکی‌پدیا گزارش می‌دهد که علاوه بر D، تلاش‌های زیادی برای کشتن C++ به یک درجه یا دیگری انجام شده است، به عنوان مثال، Vala، Cyclone، Limbo، BitC. چند نفر حتی نام چنین زبان هایی را شنیده اند؟

فکر می کنم زمان آن فرا رسیده است که از تاریخ درس بگیریم. حتی یک فرد عاقل زبان جدیدی را وارد پروژه نمی‌کند مگر اینکه شما حداقل ابزارهای توسعه معمولی را به او نشان دهید، چند داستان موفقیت به او بگویید و دوازده برنامه‌نویس به این زبان را که در نزدیکی زندگی می‌کنند به او نشان دهید. برنامه نویسان، شاید، به جز جوان ترین ها، هرگز وقت و سلامت خود را برای یادگیری صحیح ترین زبان بعدی هدر نخواهند داد، مگر اینکه ابزارهای توسعه عادی (نه کاردستی هایی مانند Racer)، چند ده هزار کتابخانه آماده را به آنها نشان دهید. نه "تجربی"، "ناپایدار" و غیره)، چند داستان موفقیت را تعریف نکنید و ده ها جای خالی باز را در شهر خود نشان دهید. مشکل مرغ و تخم مرغ به ندرت، این مشکل را می توان با موفقیت حل کرد (به طور مشروط می توان اسکالا را به عنوان مثال ذکر کرد)، عمدتاً به دلیل سرمایه گذاری زمان و پول از سوی برخی از شرکت های بزرگ (Google، Typesafe)، به دلایلی علاقه مند به محبوبیت زبان

همانطور که قبلاً اشاره کردم، دلایل غیر فنی به تنهایی بیش از حد کافی هستند. با این حال، صرفاً از روی کنجکاوی، بیایید سعی کنیم برای یک لحظه تصور کنیم که آنها آنجا نیستند. پس دلیلی برای ننوشتن در Rust وجود ندارد؟ به نظر می رسد که این نیز حداقل یک سوال بسیار بزرگ است.

C/C++ به خاطر چیزهای مختلفی مورد انتقاد قرار می گیرد. به هر حال، انتقاد اغلب توسط کسانی انجام می شود که حتی از راه دور حتی کد ++C را در تولید ندیده اند. مشکل را می توان به طور خلاصه و واضح به شرح زیر توصیف کرد: C++ بسیار سریع است (و همچنین برای حافظه، شارژ باتری و غیره نیازی ندارد)، اما ایمن نیست به این معنا که به شما امکان می دهد از مرزهای آرایه ها فراتر بروید و به اشتباه دسترسی داشته باشید. قطعات آزاد شده از حافظه، و غیره بیشتر. زمانی، این مشکل منجر به ظهور انبوهی از زبان های امن مانند جاوا، سی شارپ، پایتون و غیره شد. اما معلوم شد که این زبان ها، در مقایسه با C++، بیش از حد نیاز به منابع دارند و دارای معایب دیگری هستند، به عنوان مثال، توقف اجتناب ناپذیر جهان در هنگام جمع آوری زباله. بنابراین، مردم با وظیفه ساختن زبانی به سرعت ++C و در عین حال امن دست و پنجه نرم می کنند. یکی از این زبان ها Rust است.

زنگ در واقع امن است، اما متأسفانه، بسیار سریع نیست. در زمان نگارش، Rust از نظر سرعت با جاوا، Go و Haskell قابل مقایسه است:

من صمیمانه امیدوارم که به مرور زمان به نوعی اورکلاک شود، اما تا آن زمان، از نظر سرعت و امنیت، خیلی جالب تر از Scala یا Go نیست. این سوال هنوز باز باقی می ماند که آیا می توان یک زبان را به سرعت و ایمن ساخت، یا اینکه آیا بررسی های مداوم برای فراتر رفتن از مرزهای آرایه، صحافی ایمن در اطراف اتصالات به کتابخانه های C و غیره به طور خودکار هر زبانی را 2 برابر کندتر از C/ می کند. C++.

دقیقا چه چیزی Rust را ایمن می کند؟ به زبان ساده، این زبان با یک تحلیلگر کد استاتیک داخلی است. یک آنالایزر استاتیک واقعاً بسیار جالب که تمام خطاهای معمولی ++C را می‌گیرد، نه تنها آن‌هایی که مربوط به مدیریت حافظه هستند، بلکه چند رشته‌ای نیز هستند. من یک پیوند به یک شیء قابل تغییر را از طریق یک کانال به رشته دیگری ارسال کردم و سپس سعی کردم خودم از این پیوند استفاده کنم - کامپایل نشد. واقعا عالیه

این استدلال اغلب مطرح می شود که فقط 10٪ از کد در 90٪ مواقع اجرا می شود (که تا آنجا که من می دانم، صرفاً یک قانون سرانگشتی است - من به سرعت نتوانستم هیچ تحقیق دقیقی در مورد این موضوع پیدا کنم). بنابراین، بیشتر برنامه را می توان در Rust ایمن نوشت، با 10٪ کد داغ در زیر مجموعه ناامن نوشته شده است و کندی اجرای Rust فعلی واقعاً مشکلی ندارد. خوب، اما بعد معلوم می شود که Rust اصلاً مورد نیاز نیست، زیرا من می توانم 90٪ کد را در Go و 10٪ را در C بنویسم. فقط جویندگان گلوله نقره ای و نظریه پردازان غیرقابل لمس از Rust صرفاً به این دلیل استفاده می کنند که 100٪ برنامه را می توان به یک زبان نوشت. اگرچه در واقع این دو گویش یک زبان هستند که با ترکیب جاوا به علاوه C یا Go به علاوه C تفاوت چندانی ندارد.

در واقع، قانون 10:90 همچنان دروغ است. با این منطق، می توانید 90 درصد WebKit، 90 درصد VirtualBox یا 90 درصد GCC را در جاوا بازنویسی کنید و همان نتیجه را بگیرید. مشخصا این مورد نیست. حتی اگر موضوع این نیست که در تعدادی از برنامه ها این نگرش بسیار متفاوت است، پس مراقب دستان خود باشید. فرض کنید کل برنامه با C/C++ ناامن نوشته شده است و زمان اجرای آن، به طور نسبی، برابر با 0.9*1 (بخش کوچکی از کد داغ) + 0.1*1 (کدهای سرد زیاد) = 1 است. حال اجازه دهید آن را با برنامه‌ای به زبان امن با درج‌های Si مقایسه کنید: 0.9*1 + 0.1*2 = 1.1، تقریباً 10٪ از تفاوت. این زیاد است یا کم؟ بستگی به مقیاس شما دارد. در مورد گوگل، حتی چند درصد آن می تواند میلیون ها دلار صرفه جویی کند (نگاه کنید به نقطه 5 در مقاله، "استفاده"). یا تصور کنید که با به روز رسانی بعدی، JVM به طور ناگهانی شروع به نیاز به 10٪ منابع بیشتر می کند! من حتی می ترسم حدس بزنم در رقمی که پس از تبدیل سود به پول آمریکایی به دست می آید چند صفر خواهد بود! 10% در کارهایی که از C و C++ استفاده می شود بسیار زیاد است.

ما تکرار می کنیم "بهینه سازی زودرس ریشه همه بدی ها است" مانند یک مانترا. اما اگر آن را به معنای واقعی کلمه در نظر بگیریم، بیایید از مرتب‌سازی حبابی به جای مرتب‌سازی سریع در همه جا استفاده کنیم. ما به طور قطع نمی دانیم که برنامه در این مکان خاص کند می شود! اگر بتوانید فوراً از اتمی کارآمدتر استفاده کنید، شمارشگرهای معمولی برخی از اکشن ها را در بازیگران یا حافظه تراکنشی قرار دهید، چه فایده ای دارد؟ و به طور کلی، در موارد بی اهمیت، هیچ فایده ای برای مقداردهی اولیه همه، همه، همه متغیرها، انجام یکسری بررسی های اضافی و غیره وجود ندارد. اجازه دهید در نهایت نه با شتاب 10 درصد، بلکه 2-5 درصد. این نیز اصلاً بد نیست، اگر فقط به چند دقیقه فکر اضافی نیاز داشت. و همانطور که قبلا متوجه شدیم، در مسائل حل شده در C/C++، این می تواند یک تفاوت بزرگ باشد! سپس، چه کسی گفته است که پیدا کردن یک نقطه داغ، بازنویسی کد (احتمالاً تعداد زیادی کد) و اثبات اینکه واقعاً سریعتر است آسانتر از فکر کردن به عملکرد از قبل است؟

اگر موضوع تبادل سرعت و امنیت را نادیده بگیریم، در مورد طراحی خود زبان نیز سوالاتی دارم. به ویژه، در مورد پنج نوع اشاره گر. از یک طرف، وقتی برنامه نویس به این فکر می کند که متغیرها در کجا قرار دارند، روی پشته یا پشته، و اینکه آیا چندین رشته می توانند یا نمی توانند به طور همزمان با آنها کار کنند، این بد نیست. اما از طرف دیگر، تصور کنید که در حال نوشتن یک برنامه هستید، و معلوم می شود که متغیر باید نه روی پشته، بلکه روی پشته زندگی کند. برای استفاده از Box همه چیز را بازنویسی می کنید. بنابراین می‌دانید که چیزی که واقعاً به آن نیاز دارید Rc یا Arc است. دوباره بازنویسی کن و سپس دوباره آن را در یک متغیر معمولی در پشته بازنویسی می‌کنید. همه اینها - بدون یک IDE معمولی در دست. و بازی های معمولی کمکی نمی کند. خوب، یا فقط به سبک "Vec" >>>"، سلام جاوا! اما غم انگیزترین چیز این است که کامپایلر از قبل از طول عمر همه متغیرها مطلع است، می تواند تمام این Box، Arc و غیره را به طور خودکار خروجی دهد. اما به دلایلی این قسمت از کار منتقل می شود. نوشتن val (در هزاره سوم!) بسیار راحت تر است، و در صورت لزوم، به صراحت به Box یا Rc اشاره کنید. توسعه دهندگان Rust به این معنا کل ایده را خراب کردند.

به همین دلیل، به ویژه، دامنه کاربرد Rust بسیار محدود شده است. هیچ کس عاقلانه وب و سرور را به چنین زبانی نمی نویسد. به خصوص با توجه به اینکه مزایای قابل توجهی نسبت به زبان های مشابه تحت JVM ارائه نمی دهد. و رفتن با نخ های سبک وزن معمولی (نه آینده) برای این کارها بسیار جذاب تر به نظر می رسد. با آینده، برای اینکه به پای خود شلیک نکنید، هنوز باید کار کردن را یاد بگیرید و بگویید "زبان امن". بله، این زبان‌ها ویژگی‌های خاص خود را دارند، جهان را متوقف می‌کنند، اما این مشکل را می‌توان هم با برش به میکروسرویس‌ها و هم با تکنیک‌های دیگر حل کرد. و بله، هیچ‌کس Rust را به جاوا اسکریپت ترجمه نمی‌کند، اسکریپت‌هایی را برای طرح‌بندی در AWS در آن می‌نویسد، یا از آن به عنوان یک زبان پرس و جو برای MongoDB استفاده نمی‌کند. همچنین بعید است که آنها برای اندروید بنویسند، اما به دلیلی متفاوت - بیش از یک معماری وجود دارد، و با JVM بسیار ساده تر است. اگر ناگهان فکر کردید که Rust "برای همه کارها مناسب است"، باید شما را ناامید کنم.

خوب، به پشته:

  • ماکروها یک نسخه پشتیبان از پرحرفی بیش از حد ناشی از فقدان استثناهای عادی هستند. قبلاً در مورد مشکلات فرابرنامه‌نویسی نوشته‌ام، به ویژه، بعید است که به دلیل آن یک IDE معمولی برای Rust ببینیم. و من مطمئن نیستم، اما به نظر می رسد که ماکروهای Rust حتی فضای نام ندارند.
  • مردم احمق هستند، و محموله واقعاً کشیدن بسته‌ها را مستقیماً از مخازن git، دور زدن Crates.io تشویق می‌کند. در نتیجه احتمال خراب شدن بسته ها مانند دنیای ارلنگ با رابرش زیاد است، اتفاقاً در دنیای گو هم به نظر می رسد همین وضعیت است.
  • مانند بسیاری از زبان های جدید، Rust مسیر ساده سازی را در پیش می گیرد. به طور کلی، من می دانم که چرا هیچ وراثت عادی و استثنایی در آن وجود ندارد، اما این واقعیت که کسی چنین چیزهایی را برای من تصمیم می گیرد، طعم ناخوشایندی به جا می گذارد. C++ برنامه نویس را از نظر اینکه چه چیزی استفاده کند و چه چیزی را استفاده نکند محدود نمی کند.
  • اگر بخواهیم مسیر ساده‌سازی را طی کنیم، باید تمام این پسوندهای زبانی را کنار بگذاریم. در غیر این صورت، معلوم می شود، همانطور که در دنیای Haskell، هر برنامه نویس به گویش خود می نویسد.
  • اشاره گرهای هوشمند، در هر صورت، به دور از رایگان بودن هستند و به زمان های قابل پیش بینی جمع آوری زباله منجر نمی شوند. برخی از رشته ها به طور ناگهانی این افتخار را پیدا می کنند که یک ساختار داده بسیار عمیق را آزاد کنند. در حالی که او در لابلای پیوندهای مرده قدم می زند، رشته هایی که به او وابسته هستند، احمقانه می شوند. همین مشکل در ارلنگ با گروه های کوچکش وجود دارد، من خودم بیش از یک بار آن را مشاهده کرده ام. اشاره گرهای هوشمند نیز مشکلات خاص خود را دارند، همان پراکندگی حافظه و نشت. من vikpointer را در ساختار چرخه ای فراموش کردم، فقط همین. و این به زبانی که ادعای امن بودن دارد. اگر زمان GC قابل پیش بینی می خواهید، یا رفتار برنامه خود را تحت بار مطالعه کنید، و اگر زمان GC مناسب شما نیست، اقدام کنید (همان آبجکت ها را به خاطر بسپارید)، یا حافظه را به صورت دستی مدیریت کنید.
  • آیا کسی توصیف دقیقی از معناشناسی Rust دیده است؟ حداقل مدل حافظه داره؟ همچنین برای من یک زبان "ایمن" که "صحت" برنامه ها را ثابت می کند، که در واقع می تواند کد منبع را به ده روش مختلف تفسیر کند، ها!
  • نمی توانم یک بار دیگر این را به شما یادآوری نکنم مشکل تقریباً همیشه مردم است، نه فناوری.. اگر با کد C++ بد مواجه شدید یا سرعت جاوا به طور ناگهانی کاهش پیدا کرد، به این دلیل نیست که تکنولوژی بد است، بلکه به این دلیل است که نحوه استفاده صحیح از آن را یاد نگرفته‌اید. شما همچنین از Rust ناراضی خواهید بود، اما به دلایل مختلف. آیا یادگیری استفاده از ابزارهای محبوب تر و دوست داشتن آنها آسان تر نخواهد بود؟

به طور کلی، در طول 5 سال آینده ترجیح می‌دهم وقتم را صرف یادگیری C/C++ کنم تا Rust. C++ - این یک استاندارد صنعتی است. طیف گسترده ای از مشکلات بیش از 30 سال است که با موفقیت در این زبان حل شده اند. و Rust و امثال آن اسباب بازی های نامفهومی هستند که آینده ای مبهم دارند. حداقل از دهه 2000 صحبت هایی در مورد مرگ قریب الوقوع C++ وجود داشته است، اما نوشتن در C/C++ در این مدت کمتر آغاز شده است. دقیقا برعکس. و می بینیم که زبان در حال توسعه است (C++11، C++14)، ابزارهای جدیدی برای آن ظاهر می شوند (CLion و Clang را به یاد بیاوریم)، ​​و به سادگی تعداد زیادی جای خالی مربوطه وجود دارد.

یک برنامه نویس ++C همیشه می تواند به راحتی شغلی با حقوقی بیش از مناسب پیدا کند و در صورت لزوم سریعاً در Rust بازآموزی کند. برعکس بسیار بسیار مشکوک است. به هر حال، زبان، در هر صورت، در انتخاب یک محل کار جدید، تنها و نه عامل تعیین کننده است. علاوه بر این، یک برنامه نویس باتجربه C/C++ می تواند به راحتی کد منبع PostgreSQL یا هسته لینوکس را بررسی کند، از ابزارهای توسعه قدرتمند مدرن استفاده کند و همچنین کتاب ها و مقالات زیادی را در اختیار داشته باشد (مثلاً در OpenGL).

مراقب زمان و سلامتی خود باشید، آنقدر که فکر می کنید از آن استفاده نمی کنید!



سلام، خوانندگان عزیز!

زندگی ثابت نمی‌ماند، و O"Reilly به انتشار اولین کتاب اساسی در مورد زبان برنامه‌نویسی Rust فکر کرد:

پس از علاقه مند شدن به این موضوع، تصمیم گرفتیم ترجمه مقاله مروری در مورد زبان Rust را که در دسامبر 2014 منتشر شد، برای بحث و گفتگو مطرح کنیم. مقاله به دلیل قدیمی بودن برخی از قسمت‌های آن کمی کوتاه شده است، اما نویسنده در چارچوب جایگزین‌های موجود به خوبی به این زبان نگاه می‌کند و بر مزایا و معایب (مشروط) آن (بدون قید و شرط) تأکید می‌کند.

با این حال، برای جالب تر کردن آن، اجازه دهید در نظرات این مقاله پیوندی به مقاله دیگری درباره Rust که در یکی از وبلاگ های برنامه نویسی روسی زبان مورد علاقه ما منتشر شده است، بگذاریم. برای شروع، به سراغ گربه بروید.

سلب مسئولیت: سلیقه برای زبان های برنامه نویسی یک موضوع بسیار ذهنی است، درست مانند این پست. آن را با شک و تردید سالم بگیرید.

اخیراً چندین زبان برنامه نویسی جدید ظهور کرده اند. در میان آنها من به رست علاقه خاصی داشتم. در زیر، برداشت خود را از Rust به اشتراک می‌گذارم و آن را با چندین زبان برنامه‌نویسی دیگر مقایسه می‌کنم.

مانع یادگیری Rust

من در اولین تلاشم با Rust آشنا نشدم. چندین مانع برای یادگیری این زبان وجود دارد، از جمله:

  1. زبان به سرعت در حال تغییر است. هیچ "دیکتاتور خوش خیم برای زندگی" در Rust وجود ندارد. زبان از طریق مشارکت اعضای اصلی تیم و جامعه تکامل می یابد.
  2. با توجه به نکته اول، آموزش های Rust بسیار کم هستند. یک دفترچه راهنما، سایر اسناد رسمی وجود دارد و سایت Rust by Example منابع عالی هستند. با این حال، Rust بسیار پیچیده تر است. اغلب شما باید RFC ها، وبلاگ ها و حتی نظرات را در Github جستجو کنید تا اطلاعات مورد نیاز خود را پیدا کنید، و حتی اگر این اطلاعات همین دیروز ظاهر شد، هنوز کاملاً از آن مطمئن نیستید. من مشتاقانه منتظر یک کتاب خوب و معتبر در مورد زنگ هستم، اگرچه شرط می بندم طولانی باشد.
  3. سیستم مالکیت Rust و مکانیسم چک استقراض می تواند برای تازه کارها گیج کننده باشد. برای اطمینان از ایمنی حافظه بدون جمع‌آوری زباله، Rust از یک سیستم پیچیده وام‌گیری و مالکیت استفاده می‌کند. او اغلب نوزادان را می ترساند.
  4. کامپایلر Rust بسیار سختگیر است. من Rust را یک زبان نظم و انضباط می نامم. هر چیزی که برای کامپایلر Rust کاملاً واضح نیست، باید خودتان مشخص شود، و حتی ممکن است در ابتدا از برخی از اهداف شما آگاه نباشید. این مانع یادگیری، همراه با سایر موانع، اغلب منجر به اولین برداشت ناامیدکننده از Rust می شود.

مزایای

زنگ مزایای زیادی دارد. برخی از آنها منحصر به فرد هستند.

ایمنی حافظه بدون جمع آوری زباله

شاید این مهم ترین دستاورد Rust باشد. در زبان های برنامه نویسی سطح پایین که امکان دستکاری مستقیم حافظه را فراهم می کنند، خطاهایی مانند استفاده پس از آزاد شدن یا نشت حافظه در زمان اجرا بسیار گران هستند. در C++ مدرن، توانایی مقابله با چنین مواردی بهبود یافته است، اما نیاز به نظم فنی دقیق دارد (بخوانید: برنامه نویسان به انجام عملیات ناامن ادامه می دهند). بر این اساس، به نظر من، به طور کلی، ++C نمی تواند به طور اساسی و قابل اعتماد این مشکل را حل کند.

درست است که برنامه نویسان Rust می توانند کد ناامن را در یک بلوک ناامن بنویسند، اما (1) این کار به عمد انجام می شود و (2) بلوک های ناامن ممکن است تنها بخش بسیار کوچکی از کل پایه کد را تشکیل دهند، اما آنها به شدت کنترل می شوند.
زباله جمع کن رایج ترین ابزار ایمنی حافظه است. اگر با GC کنار بیایید، گزینه های بسیار کمی دارید. با این حال، سیستم مالکیت Rust نه تنها امنیت حافظه، بلکه امنیت داده ها و منابع را نیز تضمین می کند (به زیر مراجعه کنید).

RAII و منابع

RAII (اکتساب منابع، مقداردهی اولیه است) یک اصطلاح عجیب است، اما این ایده را به خوبی منتقل می کند. در ویکی پدیا می خوانیم که RAII با اشیاء اختصاص داده شده در پشته کار می کند. سیستم مالکیت Rust اجازه می دهد تا این اصل در مورد اشیاء تخصیص داده شده نیز اعمال شود. این باعث می شود که انتشار خودکار منابع - به عنوان مثال، حافظه، فایل ها، سوکت ها - در زمان کامپایل بسیار قابل پیش بینی و تضمین شود.
زبان‌های پویا مانند پایتون یا روبی قابلیت‌های مشابهی دارند، اما با قدرت Rust IMO مطابقت ندارند.

رقابت پذیری بدون مسابقه داده

Rust امنیت داده ها را در طول برنامه نویسی همزمان تضمین می کند - یعنی تضمین می کند که فقط بسیاری از خواننده ها یا یک "نویسنده" می توانند در هر زمان به داده ها دسترسی داشته باشند.

نوع داده جبری

Rust علاوه بر انواع معمولی (تپل ها و ساختارها)، انواع شمارش (در اینجا "انواع مجموع" یا "انواع انواع" نامیده می شود) و تطبیق الگو را نیز ارائه می دهد. تعجب آور است که یک زبان برنامه نویسی سیستمی چنین سیستم توسعه یافته ای دارد.

ترکیب بر ارث

زنگ به وضوح ترکیب نوع را به ارث ترجیح می دهد. من در اردویی هستم که این واقعیت یک برد محسوب می شود. هنگامی که Rust از انواع عمومی پشتیبانی می کند، صفات نقش کلیدی ایفا می کنند.

معایب (مشروط)

همه چیز باید خیلی واضح باشد

زنگ یک زبان منضبط است. کامپایلر باید همه چیز را کاملاً واضح و شفاف در میان بگذارد، در غیر این صورت سوگند یاد می کند تا زمانی که هیچ نقطه نامشخصی باقی نماند. این به طور کلی به نفع کیفیت کد است، اما زمانی که نوبت به نمونه‌سازی سریع یا کارهای یکباره می‌رسد، می‌تواند بیش از حد باشد.

در نتیجه: باید کدهای بهتر و واضح تری در Rust بنویسید. هنگامی که این را درک کردید، لبه های ناهموار می توانند کم و بیش ناپدید شوند.

جمع آوری زباله ثانویه است

Rust یک آشغال‌گیر بسیار ابتدایی دارد: Rc، یک شمارش مرجع، و Arc، یک شمارش مرجع اتمی بدون تشخیص دور روبین. با این حال، این ویژگی‌ها به‌طور پیش‌فرض در زبان کار نمی‌کنند و باید از مکانیسم‌های استاندارد مدیریت حافظه Rust (Stack، &، و Box) بیشتر استفاده کنید. اگر مشکلات حافظه در برنامه شما قابل توجه نباشد، باید مدل ایمنی حافظه Rust را که از جمع آوری زباله استفاده نمی کند، تحمل کنید.

بیانگر بودن به خودی خود یک هدف نیست

زبان Rust نگران بیان یا زیبایی کد نیست. قطعاً از این نظر بد نیست، اما آنقدرها هم که شما می خواهید فوق العاده نیست.

مانع ورود نسبتاً زیاد

در اصل، Rust از آن زبان‌هایی نیست که بتوانید به سرعت به آن مسلط شوید و در عرض چند هفته کدهای حرفه‌ای بنویسید. Rust شاید فشرده تر از C++ باشد، اما قطعاً از بسیاری از زبان های برنامه نویسی بزرگتر است. در مقایسه با زبان های دیگر، نمی توان آن را بسیار در دسترس نامید. اگر اولویت شما سرعت فراگیری زبان باشد، ممکن است مشکل ساز شود.

زنگ و زبان های دیگر

زبان های پویا

زبان های پویا (اسکریپت نویسی) در نقطه مقابل طیف زبان برنامه نویسی Rust قرار دارند. در مقایسه با Rust، نوشتن کد در زبان‌های پویا معمولاً سریع‌تر و آسان‌تر است. من فکر می کنم زبان های پویا در این شرایط Rust را شکست می دهند:

  • نمونه سازی سریع یا کارهای یکباره
  • کد برای تولید نیست، یا کدی که در آن خطا در زمان اجرا مشکل کوچکی است
  • پروژه شخصی (انفرادی).
  • کار نیمه خودکار (مانند تجزیه/تحلیل گزارش‌ها، پردازش متن دسته‌ای)

در چنین مواقعی نباید سعی کنید همه کارها را به خوبی انجام دهید. برعکس، Rust، به نظر من، برای موارد زیر مناسب تر است:

  • در یک تیم متوسط ​​یا بزرگ کار کنید
  • کد گرا برای استفاده طولانی مدت در تولید
  • کدی که برای مدت طولانی مورد استفاده قرار خواهد گرفت، نیاز به تعمیر و نگهداری منظم و/یا refactoring دارد
  • کدی که برای اطمینان از ایمنی تست های واحد زیادی می نویسید

به طور کلی، زمانی که کیفیت کد بسیار مهم است. زبان‌های پویا به شما کمک می‌کنند در مرحله اولیه کد را سریع‌تر بنویسید، اما بعداً کار کند می‌شود: باید تست‌های بیشتری بنویسید، خط توسعه مختل می‌شود یا حتی وقفه‌هایی در تولید رخ می‌دهد. کامپایلر Rust شما را مجبور می کند که بسیاری از کارها را در زمان کامپایل به درستی انجام دهید، زمانی که شناسایی و رفع اشکالات هزینه کمتری دارد.

برو

مقایسه این دو زبان دلیل بسیار خوبی برای بحث است، اما از آنجایی که مدتی است در حال مطالعه هستم، هنوز هم برداشت ذهنی خود را در اینجا به اشتراک خواهم گذاشت. در مقایسه با Rust، این چیزی است که من در مورد Go دوست دارم:

  • سبک وزن - زبان کوچک (و ساده، اما بسیار قدرتمند است)
  • ابزار gofmt - به طور قابل توجهی بار ذهنی را هنگام برنامه نویسی کاهش می دهد
  • گوروتین/کانال
  • تدوین فوری

چرا Go را ترک کردم:

  • خیلی مینیمالیستی است. سیستم تایپ و خود زبان چندان قابل بسط نیستند
  • برنامه نویسی برو به نظر من کمی خشک است. من را به یاد روزهایی می اندازد که در جاوا برنامه نویسی می کردم: خوب برای توسعه سازمانی، مکانیکی و ... نه چندان جالب (یادآوری: در مورد سلیقه ها اختلافی وجود ندارد)
  • محبوبیت Go به لطف پشتیبانی گوگل ادامه دارد، اما این من را کمی شک می کند. هنگامی که منافع جامعه و شرکت مطابقت نداشته باشد، ممکن است اولی قربانی شود. البته هر شرکتی در درجه اول به دنبال منافع خود است. عیبی ندارد. فقط... کمی آزاردهنده است. (بسیاری از زبان‌ها و چارچوب‌های تبلیغ شده توسط شرکت‌ها با مشکل مشابهی روبرو هستند. حداقل موزیلا به قیمت سهام وابسته نیست.)

نیم

نیم (که قبلاً نمرود نامیده می شد) زبان بسیار جالبی است. به C کامپایل می شود، بنابراین عملکرد بسیار خوب است. از نظر ظاهری شبیه پایتون است، زبانی که من همیشه برنامه نویسی را در آن دوست داشتم. این یک زبان جمع‌آوری زباله است، اما پشتیبانی نرم‌افزاری در زمان واقعی ارائه می‌دهد و رفتار جمع‌آورنده زباله خود قابل پیش‌بینی‌تر است. سیستم افکت جالبی داره. در اصل من این زبان را خیلی دوست دارم.

بزرگترین مشکل در مورد او ناپختگی اکوسیستم است. این زبان به خوبی ساخته شده و نسبتاً پایدار است، اما در حال حاضر این زبان به اندازه کافی برای موفقیت یک زبان برنامه نویسی نزدیک نیست. اسناد، کتابخانه‌های استاندارد، مخازن بسته‌ها، چارچوب‌های پشتیبانی، مشارکت جامعه و شخص ثالث... آماده کردن همه آن‌ها برای تولید آسان نیست.

بدون متخصصان برای تکمیل زبان به صورت تمام وقت، این مرحله آخر می تواند بسیار طاقت فرسا باشد. در میان زبان های برنامه نویسی جدید، Nim هنوز نمی تواند به پشتیبانی جدی ببالد.
از این رو برای او آرزوی موفقیت دارم و همچنان او را دنبال می کنم.

دیگران

زبان های دیگری مانند جولیا و . جولیا یک زبان پویا با عملکرد خوب و تماس های روان به سبک C است. (اگر به زبان های پویا و REPL علاقه دارید، توجه کنید). جولیا به لطف زمینه های عددی و علمی خود توجه همگان را به خود جلب کرده است. در حالی که این زبان پتانسیل تبدیل شدن به یک زبان همه منظوره را دارد، به نظر من توسعه یک زبان تا حد زیادی تحت تأثیر اجتماع مبتکران آن است.

D، حداقل در ابتدا، تلاشی برای ایجاد "C++، اما بهتر بود." نسخه 1.0 آن در سال 2007 منتشر شد، بنابراین این زبان چندان جدید نیست. این زبان خوبی است، اما به دلایل عینی هنوز ریشه نگرفته است: دلیل آن تقسیم شدن به فوبوس/تانگو در مراحل اولیه، و تامین امنیت حافظه در درجه اول از طریق جمع‌آوری زباله، و قرارگیری اولیه به عنوان جایگزینی برای C++.

چرا من فکر می کنم شانس Rust بسیار زیاد است

این روزها بسیاری از زبان های برنامه نویسی جدید در حال انتشار هستند. به نظر من چه چیزی باعث برجسته شدن Rust در بین آنها می شود؟ من استدلال های زیر را بیان می کنم:

یک زبان واقعی برای برنامه نویسی سیستم ها

جاسازی کار آسانی نیست. شاید بتوان آن را به معنای واقعی کلمه در چندین زبان یا حتی فقط دو زبان حل کرد: C و C++. (شاید به همین دلیل باشد که Skylight Rust را برای توسعه یک افزونه برای Ruby انتخاب کرد، حتی اگر بسیار خطرناک بود.) قابل توجه است که Rust چگونه توانسته سربار زمان اجرا را حذف کند. این یک چشم انداز منحصر به فرد را برای Rust باز می کند.

بدون نول

شی / اشاره گر تهی (به اصطلاح "اشکال میلیارد دلاری") منبع رایج خطاهای زمان اجرا است. تنها چند زبان برنامه نویسی وجود دارند که زبان های پوچ و عمدتا کاربردی ندارند. نکته این است که خلاص شدن از null نیاز به یک سیستم نوع بسیار پیشرفته دارد. به طور معمول، پرداختن به این موضوع در سطح نحوی زبان نیاز به تطبیق نوع داده و الگوی جبری دارد.

زبان سطح پایین با ساختارهای پیشرفته سطح بالا

Rust به عنوان یک «زبان فلزی برهنه» (حداقل در تئوری)، بسیاری از ویژگی‌های نسبتاً سطح بالا از جمله نوع داده جبری، تطبیق الگو، صفت، استنتاج نوع و غیره را ارائه می‌دهد.

جامعه قوی و ارتباط عملی

انجمن Rust بسیار دوستانه و فعال است. (البته این یک برداشت ذهنی است). علاوه بر این، Rust در برخی از پروژه های عملی جدی مورد استفاده قرار گرفته است - به ویژه، کامپایلر Rust، Servo، Skylight و غیره. هنوز در مرحله رشد زبان است.

تا کنون - هیچ خطای عمده ای وجود ندارد

گاهی اوقات، توسعه یک زبان یا چارچوب در یک شرکت می تواند به طور تصادفی به بن بست برسد. خوشبختانه، تیم اصلی Rust تا کنون کار بزرگی انجام داده است. همینطور ادامه بده، رست!

زنگ برای توسعه وب

اگر Rust یک زبان برنامه نویسی سیستمی است، آیا برای توسعه وب مناسب است؟ من هم به دنبال پاسخی برای این سوال هستم.

کتابخانه ها و چارچوب ها

اول از همه، برخی از کتابخانه های HTTP باید برای این کار آماده باشند. (این در وب سایت "آیا ما هنوز وب هستیم" توضیح داده شده است). اولین کتابخانه rust-http منسوخ شده است. جانشین احتمالی او Teepee عملاً در انیمیشن معلق است. خوشبختانه، هایپر کاندیدای خوبی به نظر می رسد. قبلاً در Servo، یک پروژه همزیستی Rust، پذیرفته شده است، که من آن را نعمتی برای کتابخانه HTTP برای Rust می دانم.

کتابخانه استاندارد Rust هنوز از ورودی/خروجی ناهمزمان پشتیبانی نمی کند. برای این منظور می توانید از کتابخانه خارجی mio استفاده کنید که سوکت ورودی/خروجی غیر مسدود را ارائه می دهد. پشتیبانی از نخ سبز به عنوان بخشی از ساده سازی ورودی/خروجی حذف شده است.

چندین چارچوب وب برای Rust به طور فعال در حال توسعه هستند، از جمله Iron و nickel.rs. ممکن است مدتی طول بکشد تا اوضاع با آنها آرام شود.

آیا Rust زبانی برای وب است؟

روزی کتابخانه ها و چارچوب ها آماده خواهند شد. سوال این است که آیا خود Rust برای توسعه وب مناسب است؟ آیا مدیریت حافظه سطح پایین و ویژگی های امنیتی Rust خیلی پیچیده است؟

من فکر می کنم در نهایت همه چیز بستگی به انتظار شما از پروژه دارد. در بالا، هنگام مقایسه Rust با زبان های پویا در پروژه های کوتاه مدت، اشاره کردم که در چنین مواردی، پیچیدگی Rust می تواند غیر قابل توجیه باشد. اما اگر انتظار دارید که محصول برای مدت طولانی دوام بیاورد - مثلاً شش ماه یا بیشتر - ممکن است Rust گزینه خوبی باشد.

آیا Rust برای راه اندازی وب خوب است؟

استارت آپ ها چطور؟ آنها نیاز به نمونه سازی سریع و چرخه های توسعه دارند. این یک سوال بحث برانگیزتر است، اما من روی نظر خود می ایستم: اگر به یک پروژه طولانی مدت نگاه می کنید، انتخاب زبان برنامه نویسی مناسب مهم است و Rust سزاوار توجه ویژه است. از منظر تجاری، زبانی که نمونه‌سازی سریع را امکان‌پذیر می‌کند، مزایای قابل‌توجهی را ارائه می‌دهد، در حالی که بازسازی و حذف تنگناها را همیشه می‌توان برای بعد رها کرد. واقعیت مهندسی این است که هزینه کار بازسازی معمولاً بالاتر از آن چیزی است که به نظر می رسد، و حتی اگر بسیاری از عناصر سیستم خود را تکان دهید، کدی که مدت ها پیش نوشته شده است همچنان در گوشه ای باقی می ماند. برای چندین سال.

Rust را امتحان کنید!

می توانید کمک کنید و مبلغی را برای توسعه سایت انتقال دهید



بهترین مقالات در این زمینه