Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically inferring the type of a string

Tags:

rust

Rust newbie here. What would be a good way to go about dynamically inferring the most probably type given a string? I am trying to code a function that given a string returns the most possible type but I have no idea where to start. In Python I would probably use a try-except block. This is what I would expect to have:

"4" -> u32 (or u64)
"askdjf" -> String
"3.2" -> f64

and so on? I know that some strings can be assigned to several possible types so the problem is not well defined but I am only interested in the general philosophy on how to solve the problem efficiently in rust.

like image 963
Biela Diela Avatar asked Dec 11 '22 20:12

Biela Diela


2 Answers

There is a parse method on string slices (&str) that attempts to parse a string as a particular type. You'll have to know the specific types you're ready to handle, though. The parse method can return values of any type that implements FromStr.

fn main() {
    if let Ok(i) = "1".parse::<u32>() {
        println!("{}", i);
    }
    if let Ok(f) = "1.1".parse::<f64>() {
        println!("{}", f);
    }
}

Note that the ::<T> part is only necessary if the compiler is unable to infer what type you're trying to parse into (you'll get a compiler error in that case).

like image 124
Francis Gagné Avatar answered Jan 05 '23 00:01

Francis Gagné


I am trying to code a function that given a string returns the most possible type but I have no idea where to start.

First of all: Rust is statically typed which means that a function returns one and only one type, so you can't just return different types, like in dynamically typed languages. However, there are ways to simulate dynamic typing -- namely two (that I can think of):

  1. enum: If you have a fixed number of possible types, you could define an enum with one variant per type, like this:

    enum DynType {
        Integer(i64),
        Float(f32),
        String(String),
    }
    
    fn dyn_parse(s: &str) -> DynType {
        ...
    }
    

    You can read more on enums in this and the following Rust book chapter.

  2. There is a trait in the standard library designed to simulate dynamic typing: Any. There is more information here. Your code could look like this:

    fn dyn_parse(s: &str) -> Box<Any> {
        ...
    }
    

    You can't return trait objects directly, so you have to put it in a Box.

Keep in mind that both possibilities require the user of your function to do additional dispatch. Since Rust is statically typed, you can't do the things you are used to in a dynamically typed language.

Maybe you should try to solve your problems in a different way that makes more sense in the statically typed world.


About the implementation part: Like Francis Gagné said, there is parse which tries to parse a string as a type the programmer specifies. You could of course just chain those parse calls with different types and take the first one that succeeds. But this might not be what you want and maybe not the fastest implementation.

Of course you should first think of exact rules what string should parse as what type. After that you could, for example, build a finite state machine that detects the type of the string. Doing that properly could be a bit tricky though.

like image 22
Lukas Kalbertodt Avatar answered Jan 04 '23 22:01

Lukas Kalbertodt