1

Sometimes, it’s handy to have a few instances of a struct stored and accessible everywhere.

For instance, if I want to store some meta-data about a currency in a struct like this:

struct Currency {
    name: &'static str,
    iso_symbols: Vec<&'static str>
}

I would then create an instance of Currency for every major currency. As these property don’t change, it could be hard-coded, at least for some currencies.

I tried to use const, which would work without a Vec (the vec! macro does an allocation, which is not allowed in const).

const BTC: Currency = Currency {
    name: "Bitcoin",
    iso_symbols: vec!["BTC", "XBT"]
};

So what workaround would you suggest to store a bunch of instance of Currency (for EUR, USD, BTC…)?

Here, in the Rust Playground.


EDIT: My question is quite similar to this one. The only difference is that I don’t need a mutable singleton, so the “Non-answer answer” doesn’t apply, right? The lazy_static idea is great though!

It might be interesting to keep this question around since I didn’t searched with the keyword singleton and I may not be alone to miss this way to consider the problem.

Clément Joly
  • 858
  • 9
  • 27
  • 1
    I guess you are looking for singletons. If so, you can use lazy_static crate. Take a look at https://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton. – Caio Jan 12 '19 at 16:35
  • The proposed duplicate target also works for immutable global singletons. – E_net4 Jan 12 '19 at 17:35
  • That's right @E_net4. I was just wondering if the Non-answer answer applied. – Clément Joly Jan 12 '19 at 17:50
  • 1
    Both the **non-answer answer** and the **`lazy_static`** sections apply. Being built only once and frozen afterwards makes things even easier, since you won't need to wrap it around an exclusive lock. – E_net4 Jan 12 '19 at 17:58
  • 2
    *It might be interesting to keep this question around since I didn’t searched with the keyword singleton and I may not be alone to miss this way to consider the problem.* -- This is exactly why duplicates exist! Questions marked as duplicates are not deleted, only closed to new answers. – trent Jan 12 '19 at 18:38
  • 2
    I notice that `Currency` only needs `lazy_static` because it contains a `Vec`, but if the contents of the `Vec` are known at compile time and never changed, [you could just use `&'static [&'static str]` instead](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d70485d4addb03ddde9c392b46c219af). This works with either a `const` or a `static`. – trent Jan 12 '19 at 18:45
  • @trentcl Thanks for the idea with &'static [&'static str]. Am I supposed to do something to mark the question as duplicated? – Clément Joly Jan 12 '19 at 19:21
  • @E_net4wisheshappyholidays Would you say this global state is to be avoided too, as the **non-answer** section? – Clément Joly Jan 12 '19 at 19:23
  • There should be a link you can click to agree to the duplicate, but I don't know which it is for you, maybe "close"? – trent Jan 12 '19 at 19:32
  • @trentcl I first clicked to edit my question, to explain how it was different from the duplicate, so now, I’m stuck. By the way, why didn’t you put the solution with &'static […] as an answer? – Clément Joly Jan 12 '19 at 19:42
  • Because wanting to put a `Vec` in a global static is a valid thing to do, even if it would be rare, so "just don't use `Vec`" would have been another non-answer :) – trent Jan 13 '19 at 12:05
  • @trentcl I undestand ;-) – Clément Joly Jan 13 '19 at 16:17

1 Answers1

3

As pointed out in the comments, the lazy_static crate works well.

pub struct Currency {
    name: &'static str,
    iso_symbols: Vec<&'static str>,
}

lazy_static! {
    pub static ref BTC: Currency = Currency {
        name: "Bitcoin",
        iso_symbols: vec!["BTC", "XBT"]
    };
}

fn main() {
    println!("{} {:?}", BTC.name, BTC.iso_symbols);
}

We have this global (with pub) variable BTC I was looking for.

Clément Joly
  • 858
  • 9
  • 27