These are chat archives for rust-lang/rust

22nd
Aug 2015
Thomas Koehler
@Bastacyclop
Aug 22 2015 20:34
Whats the problem with your solution ?
Ok i'm looking at the compiler error
Is what I've used
I'm on mobile right now though, so posting a semi related link is all I can do :P
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:16
Hi Kevin, thanks for the pointer. I tried to adapt it but still no luck ;) http://is.gd/vkCSOZ
Erik Hedvall
@Ogeon
Aug 22 2015 21:20
That's because your iterators has Item=&&str. You are storing &str and iter and values will return &T and not T.
Erik Hedvall
@Ogeon
Aug 22 2015 21:25
You can get around it by doing strings.iter().cloned(), strings.iter().map(|&s| s) or modifying your function to take any T::Item that can be referenced as a &str (like in the example from clap-rs):
fn print_strings<T>(strings: T) where T: IntoIterator, T::Item: AsRef<str> {
    for val in strings.into_iter() {
        println!("{}", val.as_ref());
    }
}
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:27
Ah, now I understand! If I'd use the cloned method it would actually allocate new memory for the strings, right?
Whereas by limiting Item to AsRef<str> I can get around that
Erik Hedvall
@Ogeon
Aug 22 2015 21:27
No, I'm quite sure it will just clone the reference.
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:27
ah, ok...
Erik Hedvall
@Ogeon
Aug 22 2015 21:30
...but using AsRef<str> makes it more flexible, because you can send in whatever you like (e.x. String, Cow<'a, str>, MySpecialSuperString, etc.) as long as it matches the bound.
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:30
yep, or even Path
ah, no..the other way around an AsRef<Path> can take an &str or a String
Erik Hedvall
@Ogeon
Aug 22 2015 21:31
Path? Doesn't it just support OsStr?
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:32
yep, I was mistaken...an AsRef<Path> can take &str or String but an AsRef<str> can't take a Path
Erik Hedvall
@Ogeon
Aug 22 2015 21:34
Oh, ok. Yeah, that's right. Anyway, I vote for AsRef.
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:52

Ok, now the last remaining question. Why IntoIterator instead of just Iterator:

fn print_strings<T>(strings: T) where T: Iterator, T::Item:AsRef<str> {
    for val in strings {
        println!("{}", val.as_ref());
    }
}

This also works.

Is IntoIterator more flexible and if so why?
Erik Hedvall
@Ogeon
Aug 22 2015 21:57
I just took what you had linked and changed the bounds a little, but it is actually more flexible. You can, for example, call print_strings(strings), without .iter(), since Vec<&str> implements IntoIterator<Item=&str> and that will also match the bounds.
Christoph Burgdorf
@cburgdorf
Aug 22 2015 21:58
I see! Thanks for the help :+1:
Erik Hedvall
@Ogeon
Aug 22 2015 21:58
No problem :smile: