Skip to content

Commit

Permalink
Write the "Smart Pointers" concept (#327)
Browse files Browse the repository at this point in the history
* implement smart-pointers

* minor fixes to control-flow wording

* remove duplicate heading
  • Loading branch information
0xNeshi authored Dec 30, 2024
1 parent 1d45e75 commit 7f33be6
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 7 deletions.
2 changes: 1 addition & 1 deletion concepts/control-flow/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"blurb": "Control flow in Cairo uses `if` expressions to conditionally execute code and loops to run code repeatedly.",
"blurb": "Control flow in Cairo uses `if` expressions to conditionally execute code, and loops to run code repeatedly.",
"authors": ["Falilah"],
"contributors": ["0xNeshi"]
}
2 changes: 1 addition & 1 deletion concepts/control-flow/links.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"url": "https://book.cairo-lang.org/ch02-05-control-flow.html",
"description": "Control flow concept in cairo book"
"description": "Control Flow Concept in The Cairo Book"
}
]
6 changes: 2 additions & 4 deletions concepts/smart-pointers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
{
"blurb": "<todo>",
"authors": [
"<your_gh_username>"
],
"blurb": "Smart pointers in Cairo are special data structures that manage memory safely by ensuring that memory is accessed in a controlled way.",
"authors": ["0xNeshi"],
"contributors": []
}
126 changes: 126 additions & 0 deletions concepts/smart-pointers/about.md
Original file line number Diff line number Diff line change
@@ -1 +1,127 @@
# Smart Pointers

Smart pointers in Cairo are a powerful tool that provide safe and efficient management of memory.

A smart pointer is a data structure that acts like a regular pointer, but with added safety features to avoid common memory management issues like dereferencing null pointers or accessing uninitialized memory.

## What is a Smart Pointer?

In general, a pointer is a variable that stores a memory address, typically pointing to a value stored at that location.

However, raw pointers can be dangerous: if the pointer doesn't point to valid memory or is incorrectly dereferenced, it can lead to crashes or unpredictable behavior.

Smart pointers solve this issue by enforcing strict rules on memory management, ensuring that memory is accessed in a safe and controlled manner.

Cairo, like many modern languages such as Rust, uses smart pointers to prevent unsafe memory access.

A smart pointer in Cairo not only stores a memory address but also tracks ownership and ensures memory safety.

## Types of Smart Pointers in Cairo

Cairo provides several types of smart pointers, including `Box<T>` and `Nullable<T>`, each serving a different purpose.

Let's take a closer look at how these types work and when you might use them.

### `Box<T>`

The `Box<T>` type is the principal smart pointer in Cairo.

It allows you to store data in a special memory segment called the "boxed segment." A `Box<T>` is a pointer that points to this segment, and when you create a box, you allocate space for the data in this segment.

Boxes are ideal in situations where:

- You need to store a value of a type whose size cannot be determined at compile time.
- You have a large amount of data and want to transfer ownership without copying it.

By using a box, you can store large data structures more efficiently.

When passing a `Box<T>` to a function, only the pointer is passed, avoiding the need to copy the entire data, which improves performance, especially with large structures.

### `Nullable<T>`

The `Nullable<T>` type is another important smart pointer in Cairo.

It can either point to a valid value of type `T` or be `null` if there is no value.

This type is useful in cases where you need to store values that may not always exist, such as in a dictionary that can contain optional elements.

In Cairo, `Nullable<T>` is typically used in dictionaries to handle cases where no default value can be applied.

It allows you to store values conditionally, making it easier to handle the absence of data safely.

## Memory Safety with Smart Pointers

One of the primary advantages of using smart pointers is that they help ensure memory safety.

By managing ownership and access rules, Cairo prevents common issues such as dereferencing null or dangling pointers.

Smart pointers track when data is no longer needed and can automatically deallocate memory when it goes out of scope, reducing the risk of memory leaks.

### Example: Using a `Box<T>` for Recursive Types

A common challenge in many programming languages is handling recursive types.

Recursive types refer to types that contain references to themselves.

Without proper memory management, defining a recursive type can lead to issues such as infinite recursion.

In Cairo, `Box<T>` makes it possible to define recursive types safely.

For instance, you can use `Box<T>` to implement a binary tree, where each node contains a reference to another node.

By storing references in boxes, Cairo ensures that memory usage is finite, and the compiler can determine the required memory size for the structure.

```rust
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);
}
```

### Performance Benefits of Smart Pointers

Smart pointers also improve the performance of your programs.

When you use `Box<T>`, only the pointer to the data is passed around, instead of copying the entire data structure.

This is especially useful when dealing with large datasets, as it significantly reduces the overhead of memory operations.

In the following example, the data is passed by reference using a `Box<T>` to avoid the cost of copying the entire structure:

```rust
#[derive(Drop)]
struct Cart {
paid: bool,
items: u256,
buyer: ByteArray,
}

fn pass_data(cart: Cart) {
println!("{} is shopping today and bought {} items", cart.buyer, cart.items);
}

fn pass_pointer(cart: Box<Cart>) {
let cart = cart.unbox();
println!("{} is shopping today and bought {} items", cart.buyer, cart.items);
}

fn main() {
let new_cart = Cart { paid: true, items: 1, buyer: "John" };
pass_data(new_cart);

let new_box = BoxTrait::new(Cart { paid: false, items: 3, buyer: "Jane" });
pass_pointer(new_box);
}
```

In this example, `pass_pointer` takes a `Box<Cart>` instead of a `Cart`, reducing the amount of memory copied during the function call.
4 changes: 4 additions & 0 deletions concepts/smart-pointers/introduction.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Introduction

Smart pointers in Cairo are special data structures that manage memory safely by ensuring that memory is accessed in a controlled way.
They act like regular pointers but include additional features like ownership rules and metadata to prevent common errors, such as dereferencing uninitialized memory.
This makes them essential for working with complex data structures and improving program safety and performance.
11 changes: 10 additions & 1 deletion concepts/smart-pointers/links.json
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
[]
[
{
"url": "https://book.cairo-lang.org/ch11-02-smart-pointers.html",
"description": "Smart Pointers in The Cairo Book"
},
{
"url": "https://book.cairo-lang.org/ch03-02-dictionaries.html#dictionaries-of-types-not-supported-natively",
"description": "Nullable<T> Use Case with Dictionaries"
}
]

0 comments on commit 7f33be6

Please sign in to comment.