Выбрать главу

casting

A common use for enums is to create a linked-list:

use crate::List::*;

enum List {

// Cons: Tuple struct that wraps an element and a pointer to the next node

Cons(u32, Box<List>),

// Niclass="underline" A node that signifies the end of the linked list

Nil,

}

// Methods can be attached to an enum

impl List {

// Create an empty list

fn new() -> List {

// `Nil` has type `List`

Nil

}

// Consume a list, and return the same list with a new element at its front

fn prepend(self, elem: u32) -> List {

// `Cons` also has type List

Cons(elem, Box::new(self))

}

// Return the length of the list

fn len(&self) -> u32 {

// `self` has to be matched, because the behavior of this method

// depends on the variant of `self`

// `self` has type `&List`, and `*self` has type `List`, matching on a

// concrete type `T` is preferred over a match on a reference `&T`

match *self {

// Can't take ownership of the tail, because `self` is borrowed;

// instead take a reference to the tail

Cons(_, ref tail) => 1 + tail.len(),

// Base Case: An empty list has zero length

Nil => 0

}

}

// Return representation of the list as a (heap allocated) string

fn stringify(&self) -> String {

match *self {

Cons(head, ref tail) => {

// `format!` is similar to `print!`, but returns a heap

// allocated string instead of printing to the console

format!("{}, {}", head, tail.stringify())

},

Nil => {

format!("Nil")

},

}

}

}

fn main() {

// Create an empty linked list

let mut list = List::new();

// Prepend some elements

list = list.prepend(1);

list = list.prepend(2);

list = list.prepend(3);

// Show the final state of the list

println!("linked list has length: {}", list.len());

println!("{}", list.stringify());

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Box and methods

Rust has two different types of constants which can be declared in any scope including global. Both require explicit type annotation:

   • const: An unchangeable value (the common case).

   • static: A possibly mutable variable with 'static lifetime. The static lifetime is inferred and does not have to be specified. Accessing or modifying a mutable static variable is unsafe.

// Globals are declared outside all other scopes.

static LANGUAGE: &str = "Rust";

const THRESHOLD: i32 = 10;

fn is_big(n: i32) -> bool {

// Access constant in some function

n > THRESHOLD

}

fn main() {

let n = 16;

// Access constant in the main thread

println!("This is {}", LANGUAGE);

println!("The threshold is {}", THRESHOLD);

println!("{} is {}", n, if is_big(n) { "big" } else { "small" });

// Error! Cannot modify a `const`.

THRESHOLD = 5;

// FIXME ^ Comment out this line

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The const/static RFC, 'static lifetime

Rust provides type safety via static typing. Variable bindings can be type annotated when declared. However, in most cases, the compiler will be able to infer the type of the variable from the context, heavily reducing the annotation burden.

Values (like literals) can be bound to variables, using the let binding.