Треки
/
Cairo
Cairo
/
Вправи
/
Хроносвіти: хроноланцюг
Хроносвіти: хроноланцюг

Хроносвіти: хроноланцюг

Навчальна вправа

Вступ

Розумні вказівники в Cairo - це просунуті структури даних, які забезпечують безпечне та ефективне керування памʼяттю: вони додають до звичайних вказівників запобіжні механізми й усувають типові проблеми, як-от розіменування нульового вказівника чи доступ до неініціалізованої памʼяті.

Що таке розумний вказівник?

Розумний вказівник поводиться як звичайний вказівник, але відстежує володіння та забезпечує безпечний доступ до памʼяті, запобігаючи таким проблемам, як розіменування нульового чи висячого вказівника.

Типи розумних вказівників

Cairo надає кілька типів розумних вказівників, як-от Box<T> і Nullable<T>:

  • Box<T>: зберігає дані в окремому сегменті памʼяті, що ідеально підходить для великих даних або даних з динамічним розміром. Він дає змогу передавати володіння без копіювання даних.
  • Nullable<T>: указує або на припустиме значення типу T, або на null; стає в пригоді для роботи з необовʼязковими значеннями.

Безпека памʼяті

Розумні вказівники допомагають запобігти небезпечному доступу до памʼяті: вони гарантують, що памʼять автоматично звільняється, коли більше не потрібна, і тим самим зменшують ризик витоків памʼяті.

Приклад: використання Box<T> для рекурсивних типів

Такі розумні вказівники, як Box<T>, дають змогу безпечно працювати з рекурсивними типами, наприклад з бінарним деревом: вони ефективно виділяють памʼять і запобігають нескінченній рекурсії.

use core::box::{BoxTrait};

#[derive(Copy, Drop)]
enum BinaryTree {
    Leaf: u32,
    Node: (u32, Box<BinaryTree>, Box<BinaryTree>),
}

fn main() {
    let leaf1 = BinaryTree::Leaf(1);
    let leaf2 = BinaryTree::Leaf(2);
    let node = BinaryTree::Node((3, BoxTrait::new(leaf1), BoxTrait::new(leaf2)));
    println!("{:?}", node);
}

Переваги для продуктивності

Розумні вказівники підвищують продуктивність, передаючи посилання на дані замість копіювання великих структур, що зменшує накладні витрати на памʼять.

// `Cart` is a large struct that contains a lot of information
fn pass_pointer(cart: Box<Cart>) {
    let cart = cart.unbox();
    println!("{} is shopping today and bought {} items", cart.buyer, cart.items);
}

Вказівки

У Chrono Realms Хранителі часу часто мають справу не лише з деревами часових ліній, а й із Chrono Chains - послідовностей звʼязаних TimeNodes, кожен із яких представляє конкретний момент часу. Chrono Chain - це прямий шлях із послідовних моментів, де кожен TimeNode зʼєднується з наступним. Ці Chrono Chains стають у пригоді під час подорожі крізь низку конкретних подій, адже вони дають Хранителям часу змогу рухатися однією часовою лінією.

Однак, щоб упоратися з цими потенційно довгими Chrono Chains, Хранителі часу використовують розумні вказівники (Box<t>)</t>, щоб безпечно керувати цими списками моментів і перебирати їх, не спричиняючи зайвого дублювання чи переповнення памʼяті. Кожен TimeNode зберігає посилання на наступний вузол, утворюючи рекурсивну структуру.

Наше завдання як учнів - реалізувати Chrono Chain як рекурсивну структуру списку за допомогою розумних вказівників.

У цій вправі ми зробимо таке:

  1. Створити рекурсивний enum ChronoChain, що представляє список моментів.
  2. Використати розумний вказівник Box<T> для зберігання рекурсивних вузлів.
  3. Реалізувати функцію, яка створює ChronoChain з масиву значень u32.
  4. Реалізувати функцію, яка перебирає ChronoChain й обчислює суму значень, збережених у списку.

1. Визначте рекурсивний enum ChronoChain

Створіть рекурсивний enum ChronoChain із двома варіантами:

  • End: позначає кінець списку.
  • Link: містить значення u32 і посилання на наступний вузол ланцюга, загорнуте в Box.

2. Створіть функцію для побудови ChronoChain

Напишіть функцію ChronoChain::build, яка приймає масив значень u32 і повертає ChronoChain, зʼєднуючи значення послідовно за допомогою розумних вказівників.

3. Реалізуйте функцію підсумовування

Напишіть функцію ChronoChain::sum, яка рекурсивно перебирає ChronoChain й обчислює суму значень усіх вузлів.

Приклад використання

fn main() {
    // Create a ChronoChain from an array of values
    let chrono_chain = ChronoChain::build(array![10, 20, 30]);

    // Sum the values in the ChronoChain
    let total_sum = chrono_chain.sum();

    println!("Total Time Power: {}", total_sum);
}
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Cairo Exercism

Час розпочати Хроносвіти: хроноланцюг?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Cairo, а також 25 концепцій68 вправ та справжнє наставництво від людей, і все це безкоштовно.