3

I want to initialize a Rust variable with a literal.

Shepmaster guesses that Rust has no map literal because:

the fact that there are multiple data structures that act maplike (such as both BTreeMap and HashMap) would make it hard to pick one.

But Rust says "you should probably just use Vec or HashMap", meaning that if they are good enough for most purposes, then using them when initializing from a literal value should usually work just fine.

The example map initialization is clumsy, but printing it produces a more concise representation:

{"Mars": 1.5, "Mercury": 0.4, "Earth": 1.0, "Venus": 0.7}.

fn main() {
use std::collections::HashMap;

let solar_distance = HashMap::from([
    ("Mercury", 0.4),
    ("Venus", 0.7),
    ("Earth", 1.0),
    ("Mars", 1.5),
]);

println!("{:?}", solar_distance)
}

In Python x = {"Mars": 1.5, "Mercury": 0.4, "Earth": 1.0, "Venus": 0.7} would initialize a dict variable. It would be nice if a future version of Rust would accept nested list and map literals to initialize the corresponding default Vec and HashMap structures.

Is a concise nested literal format on the Rust feature roadmap?

A second-best solution would initialize structures from a JSON string (perhaps with some syntactic sugar to avoid quote-escape hell):

fn main() {
use std::collections::HashMap;

let x = String::from("{'Venus': 0.7, 'Mars': 1.5, 'Mercury': 0.4, 'Earth': 1.0}");
println!("{:?}", x);

let solar_distance = HashMap::from(x);
println!("{:?}", solar_distance);
}

But this fails with:

    |
7   | let solar_distance = HashMap::from(x);
    |                      ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `HashMap<_, _, _>`

Has anyone written a method to initialize a nested vec/hash variable from a JSON string?

Dave
  • 3,834
  • 2
  • 29
  • 44
  • 2
    Did you consider using `Serde`? – Abdul Niyas P M Nov 25 '21 at 16:42
  • 1
    Re: closing line -- just because `println!` makes output that _looks_ like JSON given a trivial example, that's a far cry from being able to safely assert that the output _is_ JSON; the latter requires specific choices around handling of non-ASCII characters, backslash-escape sequences, etc. – Charles Duffy Nov 25 '21 at 19:20

1 Answers1

4

If you want to be able to initialize a HashMap concisely (similar to vec![]), take a look at https://crates.io/crates/hmap. It does basically exactly what you're describing.

If you want to work with serde_json, you can use the json!() macro provided by that library:

let x = json!({
  "foo": "bar",
  "baz": [1, 2, 3],
});
cameron1024
  • 9,083
  • 2
  • 16
  • 36
  • Thanks! That answered the question, which I totally mangled while writing. My motivation was to see if Rust had a native literal format like Python, which looks to the user like JSON with single quotes except that it is an actual literal structure, not a string containing JSON-ish characters. – Dave Nov 25 '21 at 17:56
  • 1
    @Dave, insofar as you can edit the question to better describe your real question while not invalidating any non-deleted answers, I'd urge you to do so. I already did a light edit to the title, but there's more to do in the body as well. – Charles Duffy Nov 25 '21 at 19:18
  • Note that `json!` gives you a `serde_json::Value`, which is an enum that can store all six primitive JSON types. If you want to get the `serde_json::Map` out, you'll need to use a `match` to destructure the `Value::Object(map)` variant. – BallpointBen Nov 28 '22 at 05:58