Bleed Less during Runtime with Rust’s Lifetime

Reading Time: 3 minutes

“Sweat more in training (Compile Time), Bleed less in Battle (Run-Time)”.

I think this old warrior mantra fits best for Rust Programmers. There are few new concepts introduced by rust-like Ownership and Lifetime, which are hard to grasp even for an experienced coder in the beginning. So the question is, why new features? And how it makes Rust different from other languages.

Why Rust?

One of the advantages which Rust gives is to control Low-Level Details. It gives you the option to choose between Stack and Heap during Runtime (Depends on preference) and also cleans down memory when not in use. Rust approach is different from C++/C or any other JVM Based Language like Java/Scala for memory cleaning. This feature allows for efficient usage of memory.   

Rust achieves safety and speed with some exciting features like Ownership, lifetimes and some more. In this blog, we are going to drill down Lifetimes.

Why Lifetimes?

In Rust, the resource can have only one owner at a time. When it goes out of scope, Rust removes it from memory. However, we can borrow data in Rust to reuse it somewhere else but the compiler should know that for how much time that acquired resource is going to be alive. This can be achieved using lifetime annotation. 

How to Use Lifetime Annotation?

In case (i),(ii) & (iii) when there is one reference input or no reference input at all. You don’t have to do it manually. The compiler does this implicitly.

 Case (i): 

fn func<'a>() -> &'a str {}      // No Argument

Case (ii):

fn function<'a>(x: &'a str) {}   // One Reference Argument

Case (iii):

fn function<'a>(x: i32, y: &'a str) -> &'a str {} // One normal and other Reference

But if there are multiple arguments of the same type. You have to tell the compiler explicitly about the lifetime of output.

Case (iv):

fn function<'a>(x: &'a str, y: &'a str) -> &'a str {} 

Case (v):

fn function<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {}

While in this case, both arguments are of different scope and output is going to have a lifetime of variable x.

Case (vi):

struct Struct<'a> {
    x: &'a str
}
enum Enum<'a> {
    Variant(&'a Type)
}

In Structure and Enum, we should mention that given lifetime as of a generic type.

Case (vii):

struct Struct<'a> {
    x: &'a str,
    y: &'a str
}
    impl<'a> Struct<'a> {
        fn fnc(x: &'a str, y: &'a str) -> Struct<'a> { }
    }

When we are using Structure with Traits, we don’t have to mention lifetime annotation in function(s) used under Implementation block.

‘Static Annotation

Rust also has static annotation which is reserved for the entire program.

fn function() -> &'static str { 
    "Static Annotation"
}

Now let’s implement whatever we learned so far with this small program.


struct Player<'a> {
    name: &'a str,
    teamName: &'a str
}
  impl<'a> Player<'a> {
      fn new(name: &'a str, teamName: &'a str) -> Player<'a> {           Person {
              name : name,
              teamName : teamName,
          }
      }

      fn teamName(&self) -> String {
          format!("{} {}", self.name , self.teamName)
      }
  }

fn main() {
    let p1 = Player::new("Dhoni", "India");
    let player_teamname = p1.teamName();

    println!("Player: {}", player_teamename);
}

Lifetime is a feature which is a little hard to grasp. But, It is Rust’s way of managing memory that makes it unique.

If you want to read more content like this?  Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7.

Happy learning!!!

This image has an empty alt attribute; its file name is screenshot-from-2020-06-08-11-00-35.png

This image has an empty alt attribute; its file name is footer-2.jpg

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading