What can be done with Rust's generic FromStr object?

前端 未结 2 576
执笔经年
执笔经年 2021-01-24 08:52

Rust\'s str class has a parse method that returns a FromStr object. parse is templated, and so the type that\'s being parsed

相关标签:
2条回答
  • 2021-01-24 09:41

    It's just not clear what m is here, as there isn't enough information to say. Is it an i32? A u64? Nobody, including Rust, can know.

    You need to do something to help figure out what type it is. Either pass it to a function expecting a specific type, or annotate it such that it can be determined what type it should be.

    0 讨论(0)
  • 2021-01-24 09:52

    Rust's str class has a parse method that returns a FromStr object.

    Stop right here, this is your error.

    parse does not return a FromStr object; FromStr is a trait which can be thought of as an abstract class if you come from an OO background, and you cannot return an object with an abstract type: it's abstract!

    What parse does return, thus, is an instance of some type T which must implement the FromStr interface.

    But failing to specify the type does not seem to be an error in itself. Instead, I get an error when trying to print the resulting (generic/unspecified) FromStr object

    Because there cannot be such generic/unspecific FromStr object. A concrete type must be inferred (from context) or explicitly spelled out, and this type must implement FromStr.

    So what is m here?

    Only you know what it should be, the compiler does not, and thus complain that it does not know what to do :)

    Or is the "unable to infer enough type information" error actually due to the fact that parse in fact can't be called without a type specifier, and the compiler just doesn't catch the error until the first line where the resulting Ok type is actually used?

    Basically.

    Except that it's not so much that the compiler doesn't catch the error until the first line where the resulting Ok is used, and more that the compiler considers the full function at once when inferring types. From the point of view of the compiler, whether the actual clue to infer the type comes immediately or comes 50 lines down does not matter, it only needs to be present in the current function body.

    It might lead to the complaint about the lack of type originating in an odd place from the developer point of view; this is one of the downfalls of type inference. On the other hand, the compiler just cannot know where YOU would prefer to put the annotation. There are after all many possibilities:

    // Example 1: immediately specifying the type
    fn main() {
        let foo = "3".parse::<i32>();
        match foo
        {
            Ok(m) => println!("foo: {}", m),
            Err(e) => println!("error! {}", e)
        }
    }
    
    // Example 2: partially specifying the result type
    // Note: the "_" is deduced to be std::num::ParseIntError because
    //       this is how `FromStr::Err` is defined for `i32`.
    fn main() {
        let foo: Result<i32, _> = "3".parse();
        match foo
        {
            Ok(m) => println!("foo: {}", m),
            Err(e) => println!("error! {}", e)
        }
    }
    
    // Example 3: specifying the result type of unwrapping
    fn doit() -> Result<(), std::num::ParseIntError> {
        let foo: i32 = try!("3".parse());
        println!("foo: {}", foo);
        Ok(())
    }
    
    fn main() {
        match doit()
        {
            Ok(_) => (),
            Err(e) => println!("error! {}", e)
        }
    }
    
    // Example 4: letting the type be inferred from a function call
    fn callit(f: i32) {
        println!("f: {}", f);
    }
    
    fn main() {
        let foo = "3".parse();
        match foo
        {
            Ok(m) => callit(m),
            Err(e) => println!("error! {}", e)
        }
    }
    
    0 讨论(0)
提交回复
热议问题