le_me
le_me

Reputation: 3419

How do I use Iterator's #map with #fold in rust?

rustc 0.13.0-nightly (f168c12c5 2014-10-25 20:57:10 +0000)

I have the following code.

fn main() {
  let nums = vec![1i,2,3];

  let strings = nums.iter()
  .map(|n| n.to_string())
  .fold(String::new, |a, b| a.push_str(b.as_slice()));

  assert_eq!("123", strings.as_slice());
}

It should convert the integers in nums to their string representations and join them to one big String.

Here's what I get from rustc:

test2.rs:6:31: 6:53 error: type `fn() -> collections::string::String` does not implement any method in scope named `push_str`
test2.rs:6   .fold(String::new, |a, b| a.push_str(b.as_slice()));
                                         ^~~~~~~~~~~~~~~~~~~~~~
test2.rs:8:29: 8:39 error: type `fn() -> collections::string::String` does not implement any method in scope named `as_slice`
test2.rs:8   assert_eq!("123", strings.as_slice());
                                       ^~~~~~~~~~
<std macros>:6:23: 6:33 error: the type of this value must be known in this context
<std macros>:6                 if !((*given_val == *expected_val) &&
                                     ^~~~~~~~~~
<std macros>:1:1: 14:2 note: in expansion of assert_eq!
test2.rs:8:3: 8:41 note: expansion site
<std macros>:6:23: 6:33 error: the type of this value must be known in this context
<std macros>:6                 if !((*given_val == *expected_val) &&
                                     ^~~~~~~~~~
<std macros>:1:1: 14:2 note: in expansion of assert_eq!
test2.rs:8:3: 8:41 note: expansion site
<std macros>:6:37: 6:50 error: the type of this value must be known in this context
<std macros>:6                 if !((*given_val == *expected_val) &&
                                                   ^~~~~~~~~~~~~
<std macros>:1:1: 14:2 note: in expansion of assert_eq!
test2.rs:8:3: 8:41 note: expansion site
<std macros>:7:23: 7:36 error: the type of this value must be known in this context
<std macros>:7                      (*expected_val == *given_val)) {
                                     ^~~~~~~~~~~~~
<std macros>:1:1: 14:2 note: in expansion of assert_eq!
test2.rs:8:3: 8:41 note: expansion site
error: aborting due to 6 previous errors

So it complains about the type fn() -> collections::string::String, but I was expecting the result of the map to be just a plain collections::string::String.

Did I do anything wrong here, or is map not supposed to be used like I tried it in the example?

EDIT:

haha ok I found the mistake, String::new is a fn() -> collections::string::String, so it was a typo!

correct is .fold(String::new(), |a, b| a.push_string(b.as_slice()));

Upvotes: 1

Views: 3948

Answers (1)

Arjan
Arjan

Reputation: 21465

There are 3 problems:

  1. String::new is missing a () and should be String::new()
  2. You have to returns a new state from the fold closure, push_str returns ().
  3. You have to make the state mutable so you can use push_str on it.

fn main() {
  let nums = vec![1i,2,3];

  let strings = nums.iter()
  .map(|n| n.to_string())
  .fold(String::new(), |mut a, b| {
        a.push_str(b.as_slice());
        a
    });

  assert_eq!("123", strings.as_slice());
}

Upvotes: 6

Related Questions