Read Json in Rust -
i trying read contents of json file in rust. file contains array of points in plane, [[1, 2], [3.5, 2.7], [0, -2.1]]
.
my first effort @ implementation is
extern crate serialize; utilize serialize::json; utilize std::io::file; fn read_points() -> vec<[f64, ..2]> { allow contents = file::open(&path::new("../points.json")).read_to_string().unwrap(); allow points: vec<vec<f64>> = json::decode(contents.as_slice()).unwrap(); points.iter().map(|&v| [v[0], v[1]]).collect::<vec<[f64, ..2]>>() }
now have 2 problems this.
first, compile error
error: cannot move out of dereference of `&`-pointer
which seems imply map operation not safe. beingness finish newbie rust, not obvious me &v
resides in memory. ideally, access underlying array backing vec<f64>
, or better, avoid allocate inner vectors read straight json vec<[f64, ..2]>
.
second - less of import - there 2 ugly unwrap
calls. now, understand both reading file , parsing json may fail. there way combine result
instances, such flatmap
in scala or bind
in haskell? better, notation?
for sec question, yes, there and_then()
method on result
, i'm afraid won't work here because error types different: read_to_string()
returns result<string, ioerror>
while json::decode()
returns result<t, decodererror>
, , can't combine them - there no generic way describe union of types in rust, can't express combined error type.
there plans ease working errors, covered this , this rfcs, maybe situation improve in future.
now reply main question.
you're getting compile error moving out of dereference because you're using iter()
, dereference pattern in closure argument @ same time. method returns iterator yields references vector - satisfies iterator<&vec<f64>>
bound. means can't move values out vector through iterator because impossible move values out of reference.
however, &v
pattern means v
should moved out reference, is, closure:
|&v| [v[0], v[1]] // v vec<f64>
is equivalent one:
|r| { // r &vec<f64> allow v = *r; // v vec<f64> [v[0], v[1]] }
this pattern useful types implicitly copyable, int
, or destructuring enums/tuples/etc, vec<t>
not implicitly copyable because has destructor , no destructuring happens here.
first, can leave &
out in &v
(you don't need specifying type parameter collect()
because inferred function homecoming type):
points.iter().map(|v| [v[0], v[1]]).collect()
the reason why can index operator translated trait method phone call automatically dereferences target.
however, express intention improve if utilize into_iter()
instead of iter()
:
points.into_iter().map(|v| [v[0], v[1]]).collect()
into_iter()
on vec<t>
returns iterator yields t
, not &t
iter()
, v
here of type vec<f64>
. into_iter()
consumes target, since points
not used after call, safe , improve expresses fact points
transformed result.
but there improve way. json decoder not back upwards deserializing statically sized arrays [f64, ..2]
because requires supporting numbers in generic parameters, , rust not have them yet. can write own type , implement decodable
it:
extern crate serialize; utilize serialize::{decoder, decodable}; utilize serialize::json; #[deriving(show)] struct point(f64, f64); impl decodable point { fn decode<d: decoder>(d: &mut d) -> result<point, d::error> { d.read_tuple(2, |d| { d.read_tuple_arg(0, |d| d.read_f64()).and_then(|e1| d.read_tuple_arg(1, |d| d.read_f64()).map(|e2| point(e1, e2) ) ) }) } } fn main() { allow s = "[[1, 2], [3.5, 2.7], [0, -2.1]]"; allow v: vec<point> = json::decode(s).unwrap(); println!("{}", v); }
(try here)
now if need [f64, ..2]
can add together method point
struct build you.
unfortunately, decodable
, decoder
underdocumented have rely on mutual sense , inspect rustc --pretty=expanded
output when seek implement them.
edit updated latest rust version
json rust
No comments:
Post a Comment