2

I want to use Rust and once_cell to implement some static const struct instance, and one static const vector contains these static struct instances.

Here's the sample code:

use once_cell::sync::Lazy;

pub struct Kind {
  name: String,
  value: i32,
}

impl Kind {
  pub fn new(name: &str, value: i32) -> Kind {
    Kind {name: String::from(name), value}
  }
}

const HYBRID: Lazy<Kind> = Lazy::new(|| Kind::new("a", 1));
const BOND: Lazy<Kind> = Lazy::new(|| Kind::new("b", 2));
// other instances

static KINDS: Lazy<Vec<Kind>> = Lazy::new(|| {
  vec![
    HYBRID,
    BOND,
    // other instances,
  ]
});

Here's the compiler error:

error[E0308]: mismatched types
  --> src/quant/fund/data/fund_info.rs:50:9
   |
50 |         HYBRID,
   |         ^^^^^^ expected struct `Kind`, found struct `once_cell::sync::Lazy`
   |
   = note: expected struct `Kind`
              found struct `once_cell::sync::Lazy<Kind>`

How should I get the real Kind inside Lazy ?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
linrongbin
  • 2,967
  • 6
  • 31
  • 59

1 Answers1

6

One option is just to create them there:

static KINDS: Lazy<Vec<Kind>> = Lazy::new(|| {
    vec![
        Kind::new("a", 1),
        Kind::new("b", 2),
        // other instances,
    ]
});

But the above way will not allow you to use the values separately, using their statics. If you do want to do that, you can store references (note that you should use static and not const for the values, see What is the difference between a constant and a static variable and which should I choose?). Since Lazy impls Deref, you can just use &*. Or you can use Lazy::force() if you want to be more explicit.

static HYBRID: Lazy<Kind> = Lazy::new(|| Kind::new("a", 1));
static BOND: Lazy<Kind> = Lazy::new(|| Kind::new("b", 2));
// other instances

static KINDS: Lazy<Vec<&Kind>> = Lazy::new(|| {
    vec![
        Lazy::force(&HYBRID),
        &*BOND,
        // other instances,
    ]
});

Or, if you need owned values, clone them:

#[derive(Clone)]
pub struct Kind { /* ... */ }

static HYBRID: Lazy<Kind> = Lazy::new(|| Kind::new("a", 1));
static BOND: Lazy<Kind> = Lazy::new(|| Kind::new("b", 2));
// other instances

static KINDS: Lazy<Vec<Kind>> = Lazy::new(|| {
    vec![
        HYBRID.clone(),
        BOND.clone(),
        // other instances,
    ]
});
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77