C13: Generic Types, Traits, and Lifetimes Flashcards

1
Q

generics

A

abstract stand-ins for concrete types or other properties
We can express the behavior of generics or how they relate to other generics without knowing what will be in their place when compiling and running the code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

lifetimes

A

Finally, we’ll discuss lifetimes: a variety of generics that give the compiler information about how references relate to each other. Lifetimes allow us to give the compiler enough information about borrowed values so that it can ensure references will be valid in more situations than it could without our help.
Lifetimes are another kind of generic that we’ve already been using. Rather than ensuring that a type has the behavior we want, lifetimes ensure that references are valid as long as we need them to be.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Generics example

A

struct Point<T> {
x: T,
y: T,
}</T>

impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}</T></T>

impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}</f32>

impl<X1, Y1> Point<X1, Y1> {
fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
Point {
x: self.x,
y: other.y,
}
}
}

fn main() {
let p = Point { x: 5, y: 10 };

println!("p.x = {}", p.x()); }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Traits

A

A trait defines functionality a particular type has and can share with other types. We can use traits to define shared behavior in an abstract way. We can use trait bounds to specify that a generic type can be any type that has certain behavior.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Trait example

A
pub trait Summary {
    fn summarize(&self) -> String;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Implementing a Trait on a Type Example

A

pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}

impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!(“{}, by {} ({})”, self.headline, self.author, self.location)
}
}

pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}

impl Summary for Tweet {
fn summarize(&self) -> String {
format!(“{}: {}”, self.username, self.content)
}
}

use aggregator::{Summary, Tweet};

fn main() {
let tweet = Tweet {
username: String::from(“horse_ebooks”),
content: String::from(
“of course, as you probably already know, people”,
),
reply: false,
retweet: false,
};

println!("1 new tweet: {}", tweet.summarize()); }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Default Implementations

A

pub trait Summary {
fn summarize(&self) -> String {
String::from(“(Read more…)”)
}
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Traits as Parameters

A

pub fn notify(item: &impl Summary) {
println!(“Breaking news! {}”, item.summarize());
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

trait bound

A

The impl Trait syntax works for straightforward cases but is actually syntax sugar for a longer form known as a trait bound; it looks like this:

pub fn notify<T: Summary>(item: &T) {
println!(“Breaking news! {}”, item.summarize());
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Returning Types that Implement Traits

A

fn returns_summarizable() -> impl Summary {
Tweet {
username: String::from(“horse_ebooks”),
content: String::from(
“of course, as you probably already know, people”,
),
reply: false,
retweet: false,
}
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

dangling references

A

reference data other than the data it’s intended to reference

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

An attempt to use a reference whose value has gone out of scope

A

fn main() {
let r;

{
    let x = 5;
    r = &x;
}

println!("r: {}", r); }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

borrow checker

A

The Rust compiler has a borrow checker that compares scopes to determine whether all borrows are valid.

fn main() {
let r; // ———+– ‘a
// |
{ // |
let x = 5; // -+– ‘b |
r = &x; // | |
} // -+ |
// |
println!(“r: {}”, r); // |
} // ———+

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Lifetime Annotation Syntax (‘)

A

Lifetime annotations don’t change how long any of the references live. Rather, they describe the relationships of the lifetimes of multiple references to each other without affecting the lifetimes.

Lifetime annotations have a slightly unusual syntax: the names of lifetime parameters must start with an apostrophe (‘) and are usually all lowercase and very short, like generic types. Most people use the name ‘a for the first lifetime annotation. We place lifetime parameter annotations after the & of a reference, using a space to separate the annotation from the reference’s type.

&i32 // a reference
&’a i32 // a reference with an explicit lifetime
&’a mut i32 // a mutable reference with an explicit lifetime

How well did you know this?
1
Not at all
2
3
4
5
Perfectly