W Rust nie ma składni literału mapy. Nie znam dokładnego powodu, ale spodziewam się, że fakt, że istnieje wiele struktur danych, które działają jak mapy (takie jak oba BTreeMap
i HashMap
), utrudniłby wybranie jednej.
Możesz jednak utworzyć makro, które wykona zadanie za Ciebie, jak pokazano w artykule Dlaczego to rdzawe makro HashMap już nie działa? . Oto makro nieco uproszczone i posiadające wystarczającą strukturę, aby można było je uruchomić na placu zabaw :
macro_rules! map(
{ $($key:expr => $value:expr),+ } => {
{
let mut m = ::std::collections::HashMap::new();
$(
m.insert($key, $value);
)+
m
}
};
);
fn main() {
let names = map!{ 1 => "one", 2 => "two" };
println!("{} -> {:?}", 1, names.get(&1));
println!("{} -> {:?}", 10, names.get(&10));
}
To makro pozwala uniknąć przydzielania niepotrzebnego elementu pośredniego Vec
, ale nie używa, HashMap::with_capacity
więc mogą wystąpić niepotrzebne realokacje w HashMap
miarę dodawania wartości. Bardziej skomplikowana wersja makra zliczającego wartości jest możliwa, ale korzyści w zakresie wydajności prawdopodobnie nie są czymś, na czym większość zastosowań tego makra skorzystałaby.
W nocnej wersji Rusta można uniknąć zarówno niepotrzebnej alokacji (i realokacji!), Jak i konieczności stosowania makra:
#![feature(array_value_iter)]
use std::array::IntoIter;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter::FromIterator;
fn main() {
let s = Vec::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = BTreeSet::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = HashSet::<_>::from_iter(IntoIter::new([1, 2, 3]));
println!("{:?}", s);
let s = BTreeMap::from_iter(IntoIter::new([(1, 2), (3, 4)]));
println!("{:?}", s);
let s = HashMap::<_, _>::from_iter(IntoIter::new([(1, 2), (3, 4)]));
println!("{:?}", s);
}
Ta logika może być następnie zawinięta z powrotem w makro:
#![feature(array_value_iter)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
macro_rules! collection {
($($k:expr => $v:expr),* $(,)?) => {
std::iter::Iterator::collect(std::array::IntoIter::new([$(($k, $v),)*]))
};
($($v:expr),* $(,)?) => {
std::iter::Iterator::collect(std::array::IntoIter::new([$($v,)*]))
};
}
fn main() {
let s: Vec<_> = collection![1, 2, 3];
println!("{:?}", s);
let s: BTreeSet<_> = collection! { 1, 2, 3 };
println!("{:?}", s);
let s: HashSet<_> = collection! { 1, 2, 3 };
println!("{:?}", s);
let s: BTreeMap<_, _> = collection! { 1 => 2, 3 => 4 };
println!("{:?}", s);
let s: HashMap<_, _> = collection! { 1 => 2, 3 => 4 };
println!("{:?}", s);
}
Zobacz też:
grabbag_macros
skrzyni. Możesz zobaczyć źródło tutaj: github.com/DanielKeep/rust-grabbag/blob/master/grabbag_macros/… .