How does Rust handle dynamic data types?

I came across a code example and I’m curious whether Rust can implement similar functionality using an array, vector, or HashMap.

I mainly work with data and want to avoid compiling every time the data structure changes. Therefore, I usually put the structure in configuration files. This solution works for me, but I am wondering if it can be done using simpler data types.

use polars::prelude::*;

fn main() {
    let a = Series::new("A", vec![1, 2, 3]);
    let b = Series::new("B", vec!["a", "b", "c"]);

    let mut df = DataFrame::new(vec![a, b]).unwrap();
    println!("{:?}", df);

    let c = Series::new("C", vec![true, false, false]);
    df.with_column(c).unwrap();
    println!("{:?}", df);

    let d = Series::new("D", vec![1.0, 2.0, 3.0]);
    let e = Series::new("E", vec![false, true, true]);

    // Also works with lazy and multiple series at once
    let df_lazy = df
        .lazy()
        .with_columns([d.lit(), e.lit()])
        .collect()
        .unwrap();
    println!("{:?}", df_lazy);
}

It's not really clear what you want. The example doesn't demonstrate anything of substance, doesn't reference any sort of configuration, and it doesn't exhibit any obvious errors either. A lot more detail and context is required.

1 Like

Sorry for the confusion, I have revised the code to make it more clear. I hope this helps.

use polars::prelude::*;

pub fn dynamic_datatype(data_configuration : &str){
    let list_of_new_column = data_configuration.split(",");
    let mut df = DataFrame::default();
    let mut i = 0;
    for add_this in list_of_new_column{
        let colname =  format!("a{}",i);

        let a = match add_this {
            "int" => Series::new(&colname, vec![1, 2, 3]),
            "str" => Series::new(&colname, vec!["A", "B", "C"]),
            _ => Series::new(&colname, vec![1, 2, 3]),
        };
        df.with_column(a).unwrap();
        i += 1;
    }
    println!("{:?}", df);
}

fn main() {
    dynamic_datatype("int,str"); // asuming i want to add 2 column, can be changes depend of parameters in configuration files
}

It sounds like you want to use serde to deserialize from "insert any serialization format here" into vectors that you can put into polars data frames.

Something like ron, maybe. You can also use JSON or pretty much any other format. The basic list is here: Overview · Serde

// config.ron
MyConfig(
    ints: {
        "A": [1, 2],
        "C": [10, 20],
    },
    strs: {
        "B": ["Hello", "World"],
        "D": ["Foo", "Bar"],
    }
)
// main.rs
use polars::prelude::*;
use serde::Deserialize;
use std::collections::HashMap;

#[derive(Deserialize)]
struct MyConfig {
    ints: HashMap<String, Vec<i32>>,
    strs: HashMap<String, Vec<String>>,
}

fn main() -> anyhow::Result<()> {
    let config = std::fs::read_to_string("./config.ron")?;
    let my_config: MyConfig = ron::from_str(&config)?;

    let mut df = DataFrame::default();
    for (k, v) in my_config.ints {
        df.with_column(Series::new(&k, v))?;
    }
    for (k, v) in my_config.strs {
        df.with_column(Series::new(&k, v))?;
    }

    println!("{df:?}");

    Ok(())
}

I appreciate your feedback. Is this approach specific to the polar dataframe? Or can the same logic be applied to other data types?

You can serialize and deserialize all data types that implement Serialize and Deserialize (that's the point). And pretty much all self-describing formats export a Value enum that allows building and deserializing values without a fixed schema.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.