How to initialize a BTreeMap within a const struct? [duplicate] - rust

This question already has answers here:
How to make a compiled Regexp a global variable?
(1 answer)
Why can't const functions in Rust make calls to associated functions?
(1 answer)
How can you make a safe static singleton in Rust?
(3 answers)
How do I create a global, mutable singleton?
(7 answers)
Closed 3 years ago.
How do I initialize a BTreeMap within a const struct?
use std::collections::BTreeMap;
struct Book {
year: u16,
volume: u8,
amendment: u8,
contents: BTreeMap<String, String>,
}
const BOOK1: Book = Book {
year: 2019,
volume: 1,
amendment: 0,
contents: BTreeMap::new(), // Issue here
};
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> src/lib.rs:14:15
|
14 | contents: BTreeMap::new(),
| ^^^^^^^^^^^^^^^

You can't. As of Rust 1.34.0, there is no function marked with const for BTreeMap. That's why you can't define a const BtreeMap at all.
The only way would be a static variable and the usage of the lazy_static crate.
use lazy_static::lazy_static; // 1.3.0
use std::collections::BTreeMap;
lazy_static! {
static ref BOOK1: Book = Book {
year: 2019,
volume: 1,
amendment: 0,
contents: BTreeMap::new()
};
}

Related

How use global static const string? [duplicate]

This question already has answers here:
How do I create a global, mutable singleton?
(7 answers)
How to create a static string at compile time
(3 answers)
What are the differences between Rust's `String` and `str`?
(14 answers)
Closed 2 years ago.
There is a ALPHABET for arithmetic, it's const and used in a lot of functions. I want make the ALPHABET global, static, and const. Some functions need the ALPHABET type as &String, but str.to_string() function will happen once memory copy. this function is called frequently, so it's not good.
The used function is a library, can't change it.
static ALPHABET: &str = "xxxxxxxxxxxxxxxxxxxxxxx";
fn some1(value: &String, alphabet: &String) -> String {
xxxx
}
fn main() {
some1("test", ALPHABET); // Can't build
some1("test", &ALPHABET.to_string()); // OK, but will happend memory copy.
}
How use the ALPHABET without to_string() function?
It would be better if your function uses &str instead:
fn some1(value: &str, alphabet: &str) -> String {
xxxx
}
Playground
Since this is in a library you cannot modify, you could use lazy_static to instantiate a static reference to the String:
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
static ref APLHABET: String = "xxxxxxxxxxxxxxxxxxxxxxx".to_string();
}
Playground

How can I use Itertools::group_by without cloning or the error "cannot move out of a value which is behind a shared reference"? [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Why can't I use a key function that returns a reference when sorting a vector with sort_by_key?
(3 answers)
Closed 2 years ago.
I have what seems to me like a simple Itertools::group_by task, but I can't make it compile unless I add clone calls.
use itertools::Itertools; // 0.9.0;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Server {
pub desc: String,
pub group_name: Option<String>,
}
fn main() {
let servers = vec![
Server {
desc: "one".to_string(),
group_name: Some("A".to_string()),
},
Server {
desc: "two".to_string(),
group_name: Some("A".to_string()),
},
Server {
desc: "three".to_string(),
group_name: None,
},
];
let mut servers_by_group_name = HashMap::new();
for (key, group) in &servers.into_iter().group_by(|s| s.group_name) {
servers_by_group_name.insert(key, group.collect::<Vec<_>>());
}
}
playground
The error is:
error[E0507]: cannot move out of `s.group_name` which is behind a shared reference
--> src/main.rs:27:59
|
27 | for (key, group) in &servers.into_iter().group_by(|s| s.group_name) {
| ^^^^^^^^^^^^
| |
| move occurs because `s.group_name` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `s.group_name.as_ref()`
The error is quite clear to me. I know I could make it go away by cloning the s.group_name in the group_by. I believe I could also use .iter() instead of .into_iter(), then it would possibly work, but then I would have a Vec<&Server> in the values of my map, but I'd really like a Vec<Server> (because my next step is wrapping that Server in a new datastructure and I really want the ownership).
Is there a way to implement this without cloning the group_name in the group_by closure?

What is the most idiomatic way of using struct methods that modify the struct's internal state from within a loop? [duplicate]

This question already has answers here:
What do I have to do to solve a "use of moved value" error?
(3 answers)
What types are valid for the `self` parameter of a method?
(2 answers)
Closed 3 years ago.
It seems to be fine to modify a vector on its own, but as soon as it is wrapped in a struct, it can not be mutated by a method on the struct.
I've created a very simplified version of my use case below, in two versions, one with just a vector, and one with a struct.
Why is it that this code is fine:
struct Task {
foo: String,
}
fn main() {
let mut list_of_tasks = Vec::new();
loop {
list_of_tasks.push(Task {
foo: String::from("bar"),
});
}
}
But this is not:
struct Task {
foo: String,
}
struct ListOfTasks(pub Vec<Task>);
impl ListOfTasks {
fn push(mut self, task: Task) {
self.0.push(task);
}
}
fn main() {
let list_of_tasks = ListOfTasks(Vec::new());
loop {
list_of_tasks.push(Task {
foo: String::from("bar"),
});
}
}
The second example fails with:
error[E0382]: use of moved value: `list_of_tasks`
--> src/main.rs:17:9
|
14 | let list_of_tasks = ListOfTasks(Vec::new());
| ------------- move occurs because `list_of_tasks` has type `ListOfTasks`, which does not implement the `Copy` trait
...
17 | list_of_tasks.push(Task {
| ^^^^^^^^^^^^^ value moved here, in previous iteration of loop
I think I'm not understanding something about moving a struct that uses mut self, but can't find any obvious examples online of how to approach this.

Store immutable instances of Rust struct, but where? [duplicate]

This question already has answers here:
How can you make a safe static singleton in Rust?
(3 answers)
How do I create a global, mutable singleton?
(7 answers)
Closed 4 years ago.
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.
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.

How to store global state in Rust when using wasm-bindgen? [duplicate]

This question already has answers here:
How do I create a global, mutable singleton?
(7 answers)
How do I keep internal state in a WebAssembly module written in Rust?
(2 answers)
Closed 4 years ago.
I'm attempting to write a data store in Rust that receives objects from JavaScript across the wasm-bindgen boundary and stores them for later retrieval. This is a simplified version of what I was hoping would work:
static mut MAP: HashMap<i32, String> = HashMap::new();
#[wasm_bindgen]
pub fn add_value(index: i32, value: String) {
unsafe {
MAP.insert(index, value);
}
}
#[wasm_bindgen]
pub fn get_value(index: i32) -> String {
unsafe {
(*MAP.get(&index).unwrap()).clone()
}
}
However I get this error from the Rust compiler:
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
How can I store state so that subsequent calls across the wasm-bindgen boundary can retrieve previously stored values?

Resources