These are chat archives for rust-lang/rust

15th
Jul 2016
Andrew De Ponte
@cyphactor
Jul 15 2016 04:32
So, I am just starting to learn rust. I have read through the Rust Book and the Rust by Examples stuff. Though, I am still confused about how to properly set the return type for a method I am writing. My method is currently as follows:
fn get_possible_files_from_glob() {
    glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
}

However when I am compile it I get the following.

src/main.rs:16:5: 16:82 error: mismatched types [E0308]
src/main.rs:16     glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:16:5: 16:82 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:16:5: 16:82 note: expected type `()`
src/main.rs:16:5: 16:82 note:    found type `std::result::Result<std::iter::Filter<std::iter::FlatMap<glob::Paths, std::result::Result<std::path::PathBuf, glob::GlobError>, [closure@src/main.rs:16:45: 16:50]>, [closure@src/main.rs:16:59: 16:80]>, glob::PatternError>`

I assume this is because it is expected the () return type because I have specified a return type for the function and it is actually getting the Result of the Filter and glob::PatternError.

Any guidance in terms of how to actually specify a return type for this function would be much appreciated.

Andrew De Ponte
@cyphactor
Jul 15 2016 05:00
Do I have to specify the return types as that crazy nested thing?
If so how do I deal with those closures in the nested return type
my hope was that I would just be able to do
fn get_possible_files_from_glob() -> std::result::Result<std::iter::Filter, glob::PatternError> {
    glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
}
however when I do that I get an error because I Filter is a generic and I am not providing enough type information for it
Alex
@Cyberunner23
Jul 15 2016 05:42
Personally i would use a match case and interpret the error then return something more convenient
Andrew De Ponte
@cyphactor
Jul 15 2016 05:43
is there no way to say I am going to return a Result of an iterator and the glob pattern error?
@Cyberunner23 ^
or I guess rather say it returns a Result with a generic type T: Iterator and the glob::PatternError?
I tried
fn get_possible_files_from_glob<T>() -> std::result::Result<T: Iterator, glob::PatternError> {
    glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
}
and get the following
```
src/main.rs:15:62: 15:63 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `:`
src/main.rs:15 fn get_possible_files_from_glob<T>() -> std::result::Result<T: Iterator, glob::PatternError> {
I am guessing that generics only work with functions like that if you are passing them in as arguments
Andrew De Ponte
@cyphactor
Jul 15 2016 05:51
@Cyberunner23 I don’t understand how doing match will help in this case. If I did it I would want it to look like this.
```
fn get_possible_files_from_glob() {
    match glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir())) {
        Ok(v) => Ok(v),
        Err(e) => Err(e)
    }
}
which would have the same complex type structure as the return type
in fact I get exactly the same error, which makes sense.
Alex
@Cyberunner23
Jul 15 2016 05:57
I would go through that complex error type and return a convenient interpretation of that error type
Andrew De Ponte
@cyphactor
Jul 15 2016 05:57
but it isn’t the error type that is complex, it is the Filter that is complex
and that is the thing I need
Alex
@Cyberunner23
Jul 15 2016 05:59
Ohh
Andrew De Ponte
@cyphactor
Jul 15 2016 06:00
So, how do I somehow simplify that return type? Or if I can’t, how do I specify the closures in the complex return type?
Alex
@Cyberunner23
Jul 15 2016 06:01
Might want to check FnOnce
also about that error with "found :" try fn get_possible_files_from_glob<T: Iterator>() -> std::result::Result<T, glob::PatternError> { glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir())) }
Andrew De Ponte
@cyphactor
Jul 15 2016 06:07
fn get_possible_files_from_glob<T: Iterator>() -> Result<T, glob::PatternError> {
    glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
}

src/main.rs:16:5: 16:82 error: mismatched types [E0308]
src/main.rs:16     glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:16:5: 16:82 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:16:5: 16:82 note: expected type `std::result::Result<T, glob::PatternError>`
src/main.rs:16:5: 16:82 note:    found type `std::result::Result<std::iter::Filter<std::iter::FlatMap<glob::Paths, std::result::Result<std::path::PathBuf, glob::GlobError>, [closure@src/main.rs:16:45: 16:50]>, [closure@src/main.rs:16:59: 16:80]>, glob::PatternError>`
Alex
@Cyberunner23
Jul 15 2016 06:08
hmm seems like Iterator is not the right type
Andrew De Ponte
@cyphactor
Jul 15 2016 06:10
I feel like I a missing something simple with this I just don’t know what it is. None of the examples I have found in any of the documentation seem to help with this situtaion. However, it seems it is would be a very common scenario.
Alex
@Cyberunner23
Jul 15 2016 06:10
are you using get_possible_files_from_glob() very ofthen by the way?
might just skip putting it in a function and truing to figure out the return type
instead to call that while line directly, long and ugly yes but might be an option
whole*
Andrew De Ponte
@cyphactor
Jul 15 2016 06:13
yeah, technically I could do that in this case. However, I am trying to understand a very common use case of returning an iterator of things.
Alex
@Cyberunner23
Jul 15 2016 06:13
ahh i see
Andrew De Ponte
@cyphactor
Jul 15 2016 06:14
I am guessing the problem is that this thing is Generics the entire way down
If we look at the type the compiler is reporting it is broken down as
std::result::Result<
    std::iter::Filter<
        std::iter::FlatMap<
            glob::Paths,
            std::result::Result<
                std::path::PathBuf,
                glob::GlobError
            >,
            [closure@src/main.rs:16:45: 16:50]
        >,
        [closure@src/main.rs:16:59: 16:80]
    >,
    glob::PatternError
>
Alex
@Cyberunner23
Jul 15 2016 06:17
ok checked the docs, found this impl<I, U, F> Iterator for FlatMap<I, U, F> where F: FnMut(I::Item) -> U, I: Iterator, U: IntoIterator
tells me that the type of the closure is FnMut(what ever the type of "a" is) for the one inside the FlatMap
well not exactly the type of "a" but "a::Item"
Andrew De Ponte
@cyphactor
Jul 15 2016 06:21
hmm
is there an identity function because that is what I was implementing with |a| a
Alex
@Cyberunner23
Jul 15 2016 06:23
whats the type of path by the way?
i think there might be a better way
wait first of all where is glob from?
Andrew De Ponte
@cyphactor
Jul 15 2016 06:26
std::path::PathBuf
Andrew De Ponte
@cyphactor
Jul 15 2016 06:34
I think this impl Trait thing has something to do with it
well it doesn’t like this
fn get_possible_files_from_glob() -> Result<impl Iterator, glob::PatternError> {
    glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir()))
}
but it is conceptually what I Want I think
Erik Hedvall
@Ogeon
Jul 15 2016 06:37
impl Trait isn't implemented yet, as far as I know
Andrew De Ponte
@cyphactor
Jul 15 2016 06:38
@Ogeon :-( do you know how to deal with lambas in the concrete types then?
Alex
@Cyberunner23
Jul 15 2016 06:38
what about
fn get_possible_files_from_glob() -> Result<impl Iterator, glob::PatternError> {
    glob("**/*").iter().filter(|path| !path.is_dir())
}
does it simplify things?
Erik Hedvall
@Ogeon
Jul 15 2016 06:40
I don't know any good way. Some of them can be replaced with functions if they don't access their environment. I would otherwise just lay down on my back and return everything as a Box<Iterator>
Andrew De Ponte
@cyphactor
Jul 15 2016 06:41
hmmm, maybe I need to read about Box
Erik Hedvall
@Ogeon
Jul 15 2016 06:42
I think you can use functions in this case, if your example is accurate
Alex
@Cyberunner23
Jul 15 2016 06:43
What about
fn get_possible_files_from_glob<T: Iterator>() -> Result<T, glob::PatternError> { glob("**/*").map(|paths| paths.flat_map(|a| a).filter(|path| !path.is_dir())) }
wait not that one...
this one
grrr keyboard...
fn get_possible_files_from_glob<T: Iterator>() -> Result<T, glob::PatternError> {
    glob("**/*").iter().filter(|path| !path.is_dir())
}
there
Erik Hedvall
@Ogeon
Jul 15 2016 06:45
T is an input type, so you can't use it like that.
Alex
@Cyberunner23
Jul 15 2016 06:45
right
Andrew De Ponte
@cyphactor
Jul 15 2016 06:45
yeah,
src/main.rs:21:45: 21:51 error: no method named `is_dir` found for type `&&glob::Paths` in the current scope
src/main.rs:21     glob("**/*").iter().filter(|path| !path.is_dir())
                                                           ^~~~~~
src/main.rs:21:5: 21:54 error: mismatched types [E0308]
src/main.rs:21     glob("**/*").iter().filter(|path| !path.is_dir())
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:21:5: 21:54 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:21:5: 21:54 note: expected type `std::result::Result<T, glob::PatternError>`
src/main.rs:21:5: 21:54 note:    found type `std::iter::Filter<std::result::Iter<'_, glob::Paths>, [closure@src/main.rs:21:32: 21:53]>`
also, iter() doesn’t work correctly. Still need the flat_map with the lamda
@Ogeon is there an identity function in Rust?
because that is what I am implementing with one of the lambdas
Right now this semes totally impossible to return the iterator that is in that code
Erik Hedvall
@Ogeon
Jul 15 2016 06:47
No prepackaged one, but here's one: fn identity<T>(x: T) -> T {x}
I got to go and I'm already late. Good luck
Alex
@Cyberunner23
Jul 15 2016 06:49
wait something like this perhaps?
fn get_possible_files_from_glob() -> Result<impl Iterator, glob::PatternError> {
    match glob("**/*") {
        Ok(paths) => {
            paths.iter().filter(|path| !path.is_dir())
        }
        Err(err) => Err(err)
    }
}
anyways its almost 3 am here, need to sleep, sorry if i couldnt help much
Andrew De Ponte
@cyphactor
Jul 15 2016 06:50
thx for trying @Cyberunner23
that one won’t work because can’t use impl keyword in return
at least not yet, there are talks about it apparently
Alex
@Cyberunner23
Jul 15 2016 06:50
ohh yea that, remove the impl, could work
Andrew De Ponte
@cyphactor
Jul 15 2016 06:51
still have the other lambda in there
which is identified as [closure@src/main.rs:18:62: 18:83]
which copying and pasted that into the return type
doesn’t work exactly
Alex
@Cyberunner23
Jul 15 2016 06:52
which has a type of FnMut(PathBuf) -> bool (i think?)
or FnMut(PathBuf::Item) -> bool
anyways good night...
Acually FnMut(&PathBuf::Item) -> bool would make more sense
ok good night for real
Andrew De Ponte
@cyphactor
Jul 15 2016 07:03
this article seems to describe iterators as difficult to type as a return value and closures as impossible
Andrew De Ponte
@cyphactor
Jul 15 2016 07:19
@Ogeon does this mean it was added? https://github.com/rust-lang/rfcs/pull/1522/files
rust-lang/rfcs#105
Erik Hedvall
@Ogeon
Jul 15 2016 16:22
@cyphactor that means that it was accepted as a new feature, but not yet implemented. Here's the tracking issue for the implementation: rust-lang/rust#34511
Erik Hedvall
@Ogeon
Jul 15 2016 16:43
Here's an idea. Note that I created it in the playground and had to fake the globs library, so there may be errors.
//Alias for the return type
type PossibleFiles = Filter<FlatMap<Paths, GlobResult, fn(GlobResult) -> GlobResult>, fn(&PathBuf) -> bool>;

fn get_possible_files_from_glob() -> Result<PossibleFiles, PatternError> {
    fn identity<T>(x: T) -> T {x}
    fn is_dir(p: &PathBuf) -> bool {!p.is_dir()}

    glob("**/*").map(|paths| paths
        .flat_map(identity as fn(_) -> _)
        .filter(is_dir as fn(&_) -> _)
    )
}
Feel free to ask if I'm doing weird stuff