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 BTreeMapi 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_capacitywięc mogą wystąpić niepotrzebne realokacje w HashMapmiarę 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_macrosskrzyni. Możesz zobaczyć źródło tutaj: github.com/DanielKeep/rust-grabbag/blob/master/grabbag_macros/… .