کتابخانهی هستهی Cairo نوعی Array را پیادهسازی میکند.
این نوع شبیه آرایههای معمول در دیگر زبانهای برنامهنویسی است، اما چند تفاوت کلیدی دارد:
Array افزود و فقط میتوان آنها را بهطور کارآمد از ابتدای آن حذف کرد.میتوان آرایهها را با تابع ArrayTrait::new و همچنین ماکروی array! ساخت:
let empty: Array<u32> = ArrayTrait::new();
let one_to_four = array![1, 2, 3, 4];
میتوان عنصرها را با تابع ArrayTrait::append به آرایه افزود:
let mut num_array = array![1, 2, 3, 4];
num_array.append(5);
// -> [1, 2, 3, 4, 5]
میتوان عنصرها را با تابع ArrayTrait::pop_front از آرایه حذف کرد:
let mut one_to_four = array![1, 2, 3, 4];
one_to_four.pop_front();
// -> [2, 3, 4]
Cairo همچنین نوع Span را معرفی میکند که مانند یک «عکس فوری» از Array عمل میکند.
هر Array را میتوان با تابع ToSpanTrait::span به یک Span تبدیل کرد:
let one_to_four = array![1, 2, 3, 4];
let one_to_four_span = one_to_four.span();
// -> [1, 2, 3, 4]
تبدیل یک آرایه به Span بسیار کارآمد است، چون Span فقط یک ساختار داده است که به Cairo اجازه میدهد بخشی از آرایه را «ببیند» و به هیچ وجه آن را تغییر نمیدهد.
Cairo با تبدیل آرایه به Span اجازه میدهد عملیات بیشتری نسبت به آنچه مستقیماً روی Array مجاز است انجام شود، مثلاً حذف یک عنصر از ابتدای Span.
let one_to_four = array![1, 2, 3, 4];
let mut one_to_four_span = one_to_four.span();
one_to_four_span.pop_back();
// -> [2, 3, 4]
توجه کنید که برای فراخوانی pop_back باید one_to_four_span را با کلیدواژهی mut تغییرپذیر میکردیم؛ این فراخوانی Span را تغییر میدهد، چون بخشی از آرایه را که Span «میبیند» کوتاهتر میکند.
الیس که میخواهد شعبدهباز شود، باید چند مبنای ساده را تمرین کند.
او یک دسته کارت دارد که میخواهد با آنها کار کند.
برای اینکه کار کمی سادهتر شود، او فقط از کارتهای ۱ تا ۱۰ استفاده میکند.
دستهی کارتها با یک Array نمایش داده میشود؛ پایین دسته در ابتدای آرایه و بالای دسته در انتهای آرایه قرار دارد.
تابع insert_top را پیادهسازی کنید؛ این تابع رونوشتی از دسته را برمیگرداند که کارت جدید دادهشده به بالای آن اضافه شده است.
let stack = array![5, 9, 7, 1];
insert_top(stack, 8);
// -> [5, 9, 7, 1, 8]
تابع remove_top_card را پیادهسازی کنید؛ این تابع رونوشتی از دسته را برمیگرداند که کارت بالاییاش برداشته شده است.
اگر دستهی دادهشده خالی باشد، باید همان دستهی اصلی بدون تغییر برگردانده شود.
let stack = array![3, 2, 6, 4, 8];
remove_top_card(stack);
// -> [3, 2, 6, 4]
تابع insert_bottom را پیادهسازی کنید؛ این تابع رونوشتی از دسته را برمیگرداند که کارت جدید دادهشده به پایین آن اضافه شده است.
let stack = array![5, 9, 7, 1];
insert_bottom(stack, 8);
// -> [8, 5, 9, 7, 1]
تابع remove_bottom_card را پیادهسازی کنید؛ این تابع رونوشتی از دسته را برمیگرداند که کارت پایینیاش برداشته شده است.
اگر دستهی دادهشده خالی باشد، باید همان دستهی اصلی بدون تغییر برگردانده شود.
let stack = array![8, 5, 9, 7, 1];
remove_bottom_card(stack);
// -> [5, 9, 7, 1]
تابع check_size_of_stack را پیادهسازی کنید؛ این تابع بررسی میکند که آیا اندازهی دسته با stack_size دادهشده برابر است یا نه.
let stack = array![3, 2, 6, 4, 8];
check_size_of_stack(stack, 4);
// -> false
برای اینکه بفهمید چرا کار کردن با آرایه در Cairo به سادگی زبانهای برنامهنویسی دیگر نیست، بهتر است این نکته را در نظر داشته باشید که Cairo از مدل حافظهی تغییرناپذیر استفاده میکند؛ یعنی وقتی در یک خانهی حافظه نوشته میشود، دیگر هرگز نمیتوان آن را بازنویسی کرد و تنها میتوان آن را خواند.
این زبان تا حدی این ویژگی را پنهان میکند و به برنامهنویسان اجازه میدهد متغیرهایشان را طوری تعریف و استفاده کنند که انگار تغییرپذیرند.
هرچند این کار نوشتن کد را کمی چالشیتر میکند، بهویژه کدی که از نوع Array استفاده میکند (از جمله ByteArray که در واقع «آرایهی بایت» است)، اما امکان نوشتن برنامههای «اثباتپذیر» را فراهم میکند؛ برنامههایی که میتوان با اطمینان آنها را حتی روی ماشینهای غیرقابلاعتماد اجرا کرد، و همین این بدهبستان را کاملاً بهصرفه میکند.