These are chat archives for rust-lang/rust

24th
Aug 2017
lemonxah
@lemonxah
Aug 24 2017 08:03
any rustconf 2017 videos online yet?
Liel Fridman
@lielfr
Aug 24 2017 19:31

Hi everyone! I'm trying to do the natural language exercise in the hash maps section of the book (second edition) and I'm getting error E0495 in the following function:

fn cmd_add(params: &mut SplitWhitespace, db: &mut HashMap<&str, Vec<&str>>) {
    let params_arr: Vec<&str> = params.collect();
    if params_arr[1] != "to" || params_arr.len() != 3 {
        println!("Error: invalid syntax.");
    } else {
        let department = db.entry(params_arr[2]).or_insert_with(Vec::new);
        department.push(params_arr[0]);
        println!("Successfully added {} to {}.", params_arr[0], params_arr[2]);
    }
}

What is the best way to solve this?

Michal 'vorner' Vaner
@vorner
Aug 24 2017 19:36
@lielfr What's error E0495? My rustc doesn't seem to know it :-(.
Joonas Koivunen
@koivunej
Aug 24 2017 19:36
@lielfr I can't remember what the E0495 was about, but my first guess would be let params_arr: Vec<&str> = params.collect(); as Iterator::collect(self) takes ownership and you have only a &mut SplitWhitespace
Liel Fridman
@lielfr
Aug 24 2017 19:36
@vorner cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
Michal 'vorner' Vaner
@vorner
Aug 24 2017 19:38
Hmm. The .collect probably deconstructs the SplitWhitespace, so the &str ones in the vec point to nowhere then.
Liel Fridman
@lielfr
Aug 24 2017 19:38
@koivunej Taking ownership doesn't seem to work
Michal 'vorner' Vaner
@vorner
Aug 24 2017 19:39
Also, you might want to check the length first and then accessing the 1st element… but that's not the cause of the error, obviously.
Joonas Koivunen
@koivunej
Aug 24 2017 19:39
@lielfr yeah, you would have received a different error
Liel Fridman
@lielfr
Aug 24 2017 19:39
@koivunej actually getting the same error
Joonas Koivunen
@koivunej
Aug 24 2017 19:39
@lielfr could you paste the whole initial error?
Liel Fridman
@lielfr
Aug 24 2017 19:39
Yes
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:13:40
   |
13 |     let params_arr: Vec<&str> = params.collect();
   |                                        ^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 12:1...
  --> src/main.rs:12:1
   |
12 | / fn cmd_add(params: SplitWhitespace, db: &mut HashMap<&str, Vec<&str>>) {
13 | |     let params_arr: Vec<&str> = params.collect();
14 | |     if params_arr[1] != "to" || params_arr.len() != 3 {
15 | |         println!("Error: invalid syntax.");
...  |
20 | |     }
21 | | }
   | |_^
note: ...so that types are compatible (expected std::str::SplitWhitespace<'_>, found std::str::SplitWhitespace<'_>)
  --> src/main.rs:13:40
   |
13 |     let params_arr: Vec<&str> = params.collect();
   |                                        ^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #4 defined on the function body at 12:1...
  --> src/main.rs:12:1
   |
12 | / fn cmd_add(params: SplitWhitespace, db: &mut HashMap<&str, Vec<&str>>) {
13 | |     let params_arr: Vec<&str> = params.collect();
14 | |     if params_arr[1] != "to" || params_arr.len() != 3 {
15 | |         println!("Error: invalid syntax.");
...  |
20 | |     }
21 | | }
   | |_^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:18:25
   |
18 |         department.push(params_arr[0]);
   |                         ^^^^^^^^^^^^^

error: aborting due to previous error(s)

error: Could not compile `employees`.
Oops, maybe too long :(
Joonas Koivunen
@koivunej
Aug 24 2017 19:41
@lielfr first of all, if you are just learning rust for the first time, you might want to consider using String's until you get to later in the book (ch 19.2 if I remember correctly)
Joonas Koivunen
@koivunej
Aug 24 2017 19:47
@lielfr adding a lifetime specifier for the cmd_add function, telling the rust compiler that all the strings in question have equal lifetimes works: https://play.rust-lang.org/?gist=ed5f6f3459aebb23547d95dfd0f4a302&version=stable
Liel Fridman
@lielfr
Aug 24 2017 19:48
@koivunej Thanks, didn't come to that chapter though
Sherab Giovannini
@Shaddy
Aug 24 2017 22:27
Why do I need to reference and dereference in this situation?
use std::collections::{HashMap, HashSet};


pub fn word_count(input: &str) -> HashMap<String, u32> {
    let mut map: HashMap<String, u32> = HashMap::new();
    let words: Vec<&str> = input.split_whitespace().collect();
    let set: HashSet<&str> = words.clone().into_iter().collect::<HashSet<&str>>();

    for word in set {
        let count = words.iter().filter(|&w| *w == word).count() as u32;
        map.insert(word.to_string(), count);
    }
    map
}
asking about this line => let count = words.iter().filter(|&w| *w == word).count() as u32;
Max Frai
@max-frai
Aug 24 2017 22:29
@Shaddy you do not reference here
but do really dereference :)
&w here is type definition
Because filter method calls lambda and passes reference
and inside you should dereference it
iter over words iterates over references, and lambda passed into filter also takes reference. You could use |w| but make double dereferencing **w
Sherab Giovannini
@Shaddy
Aug 24 2017 22:50
I see!
thanks @max-frai, pretty clear right now, for some reason I felt like something was bad written