|
1 | 1 | /*!
|
2 |
| -Macro to declare lazily evaluated statics, which allows runtime initialization. |
| 2 | +A macro for declaring lazily evaluated statics. |
3 | 3 |
|
4 |
| -The macro works by defining a custom type with a `Deref` impl, which delegates the dereferencing |
5 |
| -to a hidden `static mut` that gets lazily initialized on first access. |
| 4 | +Using this macro, it is possible to have `static`s that require code to be |
| 5 | +executed at runtime in order to be initialized. |
| 6 | +This includes anything requiring heap allocations, like vectors or hash maps, |
| 7 | +as well as anything that requires function calls to be computed. |
6 | 8 |
|
7 |
| -# Examples |
| 9 | +# Syntax |
8 | 10 |
|
9 |
| -To load the extension and use it: |
| 11 | +``` |
| 12 | +lazy_static! { |
| 13 | + static ref NAME_1: TYPE_1 = EXPR_1; |
| 14 | + static ref NAME_2: TYPE_2 = EXPR_2; |
| 15 | + ... |
| 16 | + static ref NAME_N: TYPE_N = EXPR_N; |
| 17 | +} |
| 18 | +``` |
| 19 | +
|
| 20 | +# Semantic |
| 21 | +
|
| 22 | +For a given `static ref NAME: TYPE = EXPR;`, the macro generates a |
| 23 | +unique type that implements `Deref<TYPE>` and stores it in a static with name `NAME`. |
| 24 | +
|
| 25 | +On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs |
| 26 | +can return a reference to the same object. |
| 27 | +
|
| 28 | +Like regular `static mut`s, this macro only works for types that fulfill the `Share` |
| 29 | +trait. |
| 30 | +
|
| 31 | +# Example |
| 32 | +
|
| 33 | +Using the macro: |
10 | 34 |
|
11 |
| -```rust,ignore |
| 35 | +```rust |
| 36 | +#![feature(phase)] |
12 | 37 |
|
| 38 | +#[phase(plugin)] |
| 39 | +extern crate lazy_static; |
| 40 | +
|
| 41 | +use std::collections::HashMap; |
| 42 | +
|
| 43 | +lazy_static! { |
| 44 | + static ref HASHMAP: HashMap<uint, &'static str> = { |
| 45 | + let mut m = HashMap::new(); |
| 46 | + m.insert(0u, "foo"); |
| 47 | + m.insert(1u, "bar"); |
| 48 | + m.insert(2u, "baz"); |
| 49 | + m |
| 50 | + }; |
| 51 | + static ref COUNT: uint = HASHMAP.len(); |
| 52 | + static ref NUMBER: uint = times_two(21); |
| 53 | +} |
| 54 | +
|
| 55 | +fn times_two(n: uint) -> uint { n * 2 } |
| 56 | +
|
| 57 | +fn main() { |
| 58 | + println!("The map has {} entries.", *COUNT); |
| 59 | + println!("The entry for `0` is \"{}\".", HASHMAP.get(&0)); |
| 60 | + println!("A expensive calculation on a static results in: {}.", *NUMBER); |
13 | 61 | }
|
14 | 62 | ```
|
| 63 | +
|
| 64 | +# Implementation details |
| 65 | +
|
| 66 | +The `Deref` implementation uses a hidden `static mut` that is guarded by a atomic check |
| 67 | +using the `sync::Once` abstraction. All lazily evaluated values are currently |
| 68 | +put in a heap allocated box, due to the Rust language currently not providing any way to |
| 69 | +define uninitialized `static mut` values. |
| 70 | +
|
15 | 71 | */
|
16 | 72 |
|
17 | 73 | #![crate_id = "lazy_static"]
|
|
0 commit comments