Rust Basics

Traits
  • Definition: Traits are a way to define shared behavior in Rust. They define a set of methods that a type must implement in order to fulfill the contract of the trait.
  • Purpose: Traits are used for abstracting over types, allowing you to write generic code that can work with multiple types as long as they implement the required behavior specified by the trait.
  • Syntax: Traits are declared using the trait keyword, followed by the trait’s name and a set of method signatures. Types can then implement traits using the impl keyword.
<span class="line"><span style="color: #D8DEE9">trait</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Drawable</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">draw</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&</span><span style="color: #D8DEE9">self</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Circle</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    radius</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f64</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">impl</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Drawable</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Circle</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">draw</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&</span><span style="color: #D8DEE9">self</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">Drawing a circle with radius {}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">self</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">radius</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
Closures
  • Definition: Closures are anonymous functions that can capture variables from their surrounding environment. They are similar to functions but are defined inline using a concise syntax.
  • Purpose: Closures are useful for writing code that requires a small, one-off function without the need to define a separate named function. They are often used for passing behavior as arguments to higher-order functions.
  • Syntax: Closures are written using a pipe (|) syntax to specify the parameters, followed by the body of the closure. They can capture variables from their enclosing scope using a move or borrow semantics.
<span class="line"><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">add</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9">x</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">| x + y</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">The sum is: {}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">3</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
where clause

In Rust, the where clause is used in function declarations, trait declarations, and various other contexts to specify additional requirements or bounds on the generic parameters or associated types.

When used in a function declaration, the where clause typically follows the list of generic parameters and is used to specify trait bounds or additional constraints on those parameters.

= (1..5).map(|x| x * x).collect(); println!(“{:?}”, squares); // This will print [1, 4, 9, 16] } ‘ style=”color:#d8dee9ff;display:none” aria-label=”Copy” class=”code-block-pro-copy-button”>
<span class="line"><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">squares</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Vec</span><span style="color: #ECEFF4"><</span><span style="color: #D8DEE9FF">i32</span><span style="color: #ECEFF4">></span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">1..5</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">map</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9">x</span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">collect</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">{:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">squares</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// This will print [1, 4, 9, 16]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
  1. Range Creation:let range = 1..5;
  2. Mapping Function:let squares = range.map(|x| x * x);
    • The map method takes a closure |x| x * x which squares each element x in the range.
  3. Collecting Results:let squares: Vec<i32> = squares.collect();
    • The collect method is used to consume the iterator and collect the results into a vector.
  4. This creates a range from 1 to 4.
core::array::from_fn

The core::array::from_fn function in Rust is a utility that allows you to generate an array of fixed size by applying a closure to each index.

<span class="line"><span style="color: #D8DEE9">use</span><span style="color: #D8DEE9FF"> core</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF">:</span><span style="color: #D8DEE9">array</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Create an array of 10 elements where each element is its index squared</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">squares</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> [usize; </span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">array</span><span style="color: #D8DEE9FF">::</span><span style="color: #88C0D0">from_fn</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">{:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">squares</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// Prints: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
Option<T>

Option<T> is an enum in Rust that represents an optional value. It can be either:

  • Some(T): Indicates that there is a value of type T.
  • None: Indicates that there is no value.

The Option type is used extensively in Rust to handle cases where a value might be absent

if let

In Rust, the if let construct is used to match a pattern and execute code if the match is successful. It can be used to handle Option and Result types more ergonomically. Specifically, if let Some(next) = inputs_iter.peek() checks if peek() returns Some and extracts the value into next. If peek() returns None, the else block is executed.

<span class="line"><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Define a vector of vectors</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inputs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">vec</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">vec</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">[</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">vec</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">[</span><span style="color: #B48EAD">4</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">6</span><span style="color: #D8DEE9FF">]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">vec</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">[</span><span style="color: #B48EAD">7</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">9</span><span style="color: #D8DEE9FF">]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ]</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Convert the vector into an iterator and make it peekable</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mut</span><span style="color: #D8DEE9FF"> inputs_iter </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inputs</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">into_iter</span><span style="color: #D8DEE9FF">()</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">peekable</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Loop through the iterator</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Some</span><span style="color: #D8DEE9FF">(current) </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inputs_iter</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">next</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Print the current element</span></span>
<span class="line"><span style="color: #D8DEE9FF">        println!(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">Current: {:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> current);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Peek at the next element</span></span>
<span class="line"><span style="color: #D8DEE9FF">        if let </span><span style="color: #88C0D0">Some</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">next</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> = inputs_iter.</span><span style="color: #88C0D0">peek</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// If there is a next element, print it</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">Next: {:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">next</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> else </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// If there are no more elements, print a message</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">No more elements.</span><span style="color: #ECEFF4">"</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
Ownership & borrowing

In Rust, “ownership” refers to the ownership system that Rust uses to manage memory safely without a garbage collector. Ownership is a set of rules that governs how memory is managed, ensuring that memory is freed when it is no longer needed.

When we say that a function or method takes ownership of data, it means that the function or method takes control over the data, and the original owner can no longer access the data. Conversely, when we say that a function or method borrows data, it means that the function or method can temporarily use the data, but the original owner retains control and can continue to use it once the borrowing ends.

ownership:

) { // `v` is borrowed here, not owned println!(“{:?}”, v); } fn main() { let v = vec![1, 2, 3]; borrow(&v); // v is still accessible here because its ownership was not transferred println!(“{:?}”, v); // This is fine } ‘ style=”color:#d8dee9ff;display:none” aria-label=”Copy” class=”code-block-pro-copy-button”>
<span class="line"><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">borrow</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF">: </span><span style="color: #81A1C1">&</span><span style="color: #D8DEE9">Vec</span><span style="color: #81A1C1"><</span><span style="color: #D8DEE9">i32</span><span style="color: #81A1C1">></span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// `v` is borrowed here, not owned</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">{:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">fn</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #D8DEE9FF">() </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">let</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">vec</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">[</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">]</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">borrow</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&</span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// v is still accessible here because its ownership was not transferred</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">println</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">"</span><span style="color: #A3BE8C">{:?}</span><span style="color: #ECEFF4">"</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// This is fine</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
Immutable borrowing

When you borrow a value immutably, you use &. This means that the function can read the value but cannot modify it

mutable borrowing

When you borrow a value mutably, you use &mut. This allows the function to modify the value

Leave a Reply

Your email address will not be published. Required fields are marked *