daniellga
daniellga

Reputation: 1224

function output type varying with input

I have a function like this, where the user of the function specifies the type of the output:

pub fn test(user_input: &str, number: f32) -> ??? {
    if user_input == "f32"{
        number as f32
    } else if user_input == "f64" {
        number as f64
    } else {
        panic!();
    }
}

I am rather new to Rust, so I ask you, how can I make this function return the type asked by the user? I am interested only in f32 and f64 outputs.

Upvotes: 1

Views: 558

Answers (2)

Jan Hudec
Jan Hudec

Reputation: 76246

You can't. Rust is statically typed language, so the type must be known at compile time. It cannot depend on user input.

What you could do instead is define a union type, like:

enum Float {
    Single(f32),
    Double(f64),
}

and then write

pub fn test(user_input: &str, number: f32) -> Float {
    if user_input == "f32"{
        Single(number as f32)
    } else if user_input == "f64" {
        Double(number as f64)
    } else {
        panic!();
    }
}

I don't see how such function would ever be useful though.

Update: Or you can create a common trait, but in return position you have to box it. Like:

trait Float { … }

impl Float for f32 { … }

impl Float for f64 { … }

and then write

pub fn test(user_input: &str, number: f32) -> Box<dyn Float> {
    if user_input == "f32"{
        Box::new(number as f32)
    } else if user_input == "f64" {
        Box::new(number as f64)
    } else {
        panic!();
    }
}

This makes sense for large objects (like whole buffer with associated codec), but for single values the overhead is relatively huge.

Upvotes: 5

Deadbeef
Deadbeef

Reputation: 1681

If you only want to convert based on what the caller of the function needs, maybe try this:

fn t_from_f32<T: From<f32>>(f: f32) -> T {
    f.into()
}

Then you can call this function like this:

fn main() {
    let f = 1.0;

    // bind to a local variable with explicit types
    let double: f64 = t_from_f32(f);
    let float: f32 = t_from_f32(f);
    
    // .. or use turbofish syntax for the function call
    let turbofish_double = t_from_f32::<f64>(f);
}

Upvotes: 0

Related Questions