i'm writing case-insensitive anagram finder given word , list of words. have following code:
pub fn anagrams_for(s: &'static str, v: &[&'static str]) -> vec<&'static str> { let mut s_sorted: vec<_> = s.to_lowercase().chars().collect(); s_sorted.sort(); v.iter().filter_map(move |word: &str| { let mut word_sorted: vec<_> = word.to_lowercase().chars().collect(); word_sorted.sort(); if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() { some(word) } else { none } }).collect() } the logic of sort lowercase given word, , each word in vector, same. if words different pre-sort (to eliminate self-anagrams) same post-sort, add output.
the above seems have problems capturing s , s_sorted surrounding scope, though, because when compile following error:
error: type mismatch: type
[closure@src/lib.rs:23:25: 32:6 s_sorted:_, s:_]implements traitfor<'r> core::ops::fnmut<(&'r str,)>, traitcore::ops::fnmut<(&&str,)>required (expected &-ptr, found str)
when looked @ description of error type ([e0281]), found following tl;dr:
the issue in case
foodefined acceptingfnno arguments, closure attempted pass requires 1 argument.
this confusing because thought move closures capture variables surrounding scope.
what missing?
this doesn't have capturing variables in closure. let's check out error message again, reformatted bit:
type mismatch: type `[closure@<anon>:5:25: 14:6 s_sorted:_, s:_]` implements trait `for<'r> core::ops::fnmut<(&'r str,)>`, trait `core::ops::fnmut<(&&str,)>` required (expected &-ptr, found str) and more clearly:
found: for<'r> core::ops::fnmut<(&'r str,)> expected: core::ops::fnmut<(&&str,)> and zooming in further:
found: &'r str expected: &&str the culprit this: |word: &str|.
you have declared closure accepts string slice, that's not iterator yields. v slice of &str, , iterator on slice returns references items in slice. each iterator element &&str.
change closure |&word| , work. uses pattern matching dereference closure argument once before value bound word. equivalently (but less idiomatically), use |word| , *word inside closure.
additionally...
you don't need restrict
'staticstrings:pub fn anagrams_for<'a>(s: &str, v: &[&'a str]) -> vec<&'a str> {it doesn't need
moveclosure.- extract logic of creating vector of sorted chars. helps ensure logic stays consistent between 2 and means don't have declare vectors mutable longer needed.
fn sorted_chars(s: &str) -> vec<char> { let mut s_sorted: vec<_> = s.to_lowercase().chars().collect(); s_sorted.sort(); s_sorted } pub fn anagrams_for<'a>(s: &str, v: &[&'a str]) -> vec<&'a str> { let s_sorted = sorted_chars(s); v.iter().filter_map(|&word| { let word_sorted = sorted_chars(word); if word_sorted == s_sorted && s.to_lowercase() != word.to_lowercase() { some(word) } else { none } }).collect() } fn main() {}
Comments
Post a Comment