Skip to content

Const Generics #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jesskfullwood opened this issue Apr 5, 2020 · 1 comment
Open

Const Generics #7

jesskfullwood opened this issue Apr 5, 2020 · 1 comment

Comments

@jesskfullwood
Copy link

jesskfullwood commented Apr 5, 2020

I'm still interested in the ideas behind this project. Had a play to see how const generics might make the API more expressive, and I think it has a lot of potential. The idea is that const-generics would allows you to insert and retrieve columns into the dataframe by name, and it would be a compile error to ask for a column that didn't exist. Take this toy code (using frunk which is great):

#![feature(const_generics)]

use frunk::hlist::{HList, HCons, HNil, Selector};

struct Column<T, const S: &'static str> {    // S is the 'name' of the column
    inner: Vec<T>
}

impl<T, const S: &'static str> Column<T, S> {
    fn new(inner: Vec<T>) -> Self {
        Self {
            inner
        }
    }
}

struct Frame<H: HList> {
    inner: H
}

impl Frame<HNil> {
    fn new() -> Self {
        Self {
            inner: HNil
        }
    }
}

impl<H: HList> Frame<H> {
    fn add<T, const S: &'static str>(self, col: Vec<T>) -> Frame<HCons<Column<T, S>, H>> {
        let column = Column::new(col);
        Frame {
            inner: HCons{
                head: column,
                tail: self.inner
            }
        }
    }

    pub fn get<T, Index, const S: &'static str>(&self) -> &Column<T, S>
    where
        H: Selector<Column<T, S>, Index>,
    {
        Selector::get(&self.inner)
    }
}

fn main() {
    let frame = Frame::new()
        .add::<u32, "col1">(vec![1,2,3])
        .add::<u32, "col2">(vec![1,2,3]);
    let col = frame.get::<_, _, "col1">();  // OK
    // let col = frame.get::<_, _, "missing">();  // compile error!
}

This is pretty neat! Problem: it crashes with an ICE at the moment. But it will work soon!

@xcaptain
Copy link

@jesskfullwood Great, I implemented get_column based on your work

pub fn get_column<Index, T>(&self) -> T
where Col: Sculptor<T, Index>
{
    let (target, _): (T, _) = self.inner_cols.clone().sculpt();
    target
}

using Sculptor go get the specific columns.

I also implemented a simple get_row

pub fn get_row<Index, T1: Copy, const S1: &'static str, T2: Copy, const S2: &'static str>(&self, idx: usize) -> (T1, T2)
where Col: Sculptor<HCons<Column<T1, S1>, HCons<Column<T2, S2>, HNil>>, Index>
{
    let (target, _): (HCons<Column<T1, S1>, HCons<Column<T2, S2>, HNil>>, _) = self.inner_cols.clone().sculpt();
    let list: (Column<T1, S1>, Column<T2, S2>) = target.into();
    (list.0.inner[idx], list.1.inner[idx])
}

This get_row works, but is not generic, do you have any idea on implement a better get_row?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants