Giter Site home page Giter Site logo

Comments (9)

zhiburt avatar zhiburt commented on June 2, 2024 2

Good idea.
Will you open a PR?

I am confident somebody who is good with macros could improve this 2x

Well here's not 2x but I think a bit better.

    ( $($table:expr), *; $N:expr) => {{
        let groupings = &[$($table.to_string(),)*];
        let groups = groupings
            .chunks($N)
            .map(|chunk| {
                chunk.iter()
                    .map(ToString::to_string)
                    .chain(std::iter::repeat(String::default()))
                    .take($N)
            });

        let mut builder = tabled::builder::Builder::default();
        // todo: (yet not merged) builder.hint_size($N);

        for group in groups {
            builder.add_record(group);
        }

        builder.build()
    }};

from tabled.

IsaacCloos avatar IsaacCloos commented on June 2, 2024 1

🙋🏻‍♂️

If this ticket is still available I'd like to draft a solution or two for you 😃

from tabled.

zhiburt avatar zhiburt commented on June 2, 2024 1

Hello @IsaacCloos, feel free to try it.

Remember that rows in some tables might be multiline.

I am also thinking how would Width be applied to this type.
But it's specifics and it may not be as it's done in ExpandedDisplay.

PS: The code base was changed quite a bit from your last look I guess. I think its better but if you have any question ping me.

from tabled.

zhiburt avatar zhiburt commented on June 2, 2024 1

I actually very suprised how you managed it.
I mean such an idea didn't came to my mind.
I was always picturing it to be done as a different type which would probably have some unique methods (which I am not sure what they are).

Very elegant solution.

Notes:

  1. We could use tuple instead of a new type TableGroup. Not sure which is better but in your case we have a type check. In tuple case any fmt::Display will work.

    macro_rules! parallel {
        ( $($table:expr),* ) => {{
            Table::new([( $($table.to_string(),)*) ])
                .with(Style::empty())
                .with(Extract::rows(1..))
        }};
    }
  2. I think Extract call is less efficient than this

    let mut b = Table::builder([TableGroup($($table,)*)]);
    b.remove_columns();
    b.build().with(Style::empty())
  3. It could be cool to be able to use &Table in input.

    parallel!(&table_a, &table_b)
  4. I would not change a default Style to act as default Table::new.

I am thinking is there any options we could provide to the macros?
Do you have any ideas?

from tabled.

zhiburt avatar zhiburt commented on June 2, 2024 1

I am thinking if parallel![table; 4] would be any useful, if it would behave as vec![table; 4]

from tabled.

zhiburt avatar zhiburt commented on June 2, 2024 1

Also I am thinking if it must be a macro actually.
At your initial code it must has been.

But if you'll look at mine example there's nothing there which stopes it being a function.

from tabled.

IsaacCloos avatar IsaacCloos commented on June 2, 2024

Hello, I have a draft of a lightweight enhancement for this feature.

This is the first time I've written macros so please don't hold back on criticism.
Feedback makes a HUGE difference for me 😄

macro code:

macro_rules! replace_expr {
    ($_t:tt $sub:ty) => {
        $sub
    };
}

macro_rules! group_builder {
    ( $($typ:ty),* ) => {
        #[derive(Tabled)]
        struct TableGroup($($typ,)*);
    }
}

macro_rules! parallel {
    ( $($table:expr),* ) => {{

        group_builder!( $(
            replace_expr!(
                ($table)
                Table
            )
        ),*);

        Table::new([TableGroup($($table,)*)])
            .with(Style::empty())
            .with(Extract::rows(1..))
    }};
}

full example file found here for you to run and review

the following are my opinions on this solution:

pros

  • utilizes existing apis to deliver the desired result. minimal code bloat
  • highly flexible. max number of parallel tables is governed by the recursion_limit
  • leverages the powerful nested tables feature to prevent side-by-side tables from conflicting each-others styles
  • idea could be expanded to a more general tool to group tables. this could improve the ergonomics of creating nested tables

cons

  • general macro trade offs (longer compile times, ext)
  • solution exists outside the core codebase and could easily be disrupted by changes to several different apis
  • to me it feels a bit 'hacky' to assemble new tables 'invisibly', but I do like the ergonomics of easily making side-by-side displays like this

Again, your feedback means a lot to me. If you are interested in this kind of approach I can clean it up and make a proper PR with tests, example, documentation, the usual 👍🏻

from tabled.

IsaacCloos avatar IsaacCloos commented on June 2, 2024

Great feedback 🤩

I learned a LOT about Rust and Tabled from this issue so far 👍🏻

New proposal (with your feedback)

macro_rules! parallel {
    ( $($table:expr), * ) => {{
        let mut builder = Table::builder([( $($table.to_string(),)*) ]);
        builder.remove_columns();
        builder.build()
    }};
}

Achieves original ticket goal with minimal code complexity and 0 refactoring necessary 👍🏻

Rough Draft of extending concept

I am thinking is there any options we could provide to the macros?
Do you have any ideas?

macro_rules! parallel_plus {
    ( $($table:expr), * ) => {{
        let mut builder = Table::builder([( $($table.to_string(),)*) ]);
        builder.remove_columns();
        builder.build()
    }};

    ( $($table:expr), *; $N:expr) => {{
        let groupings = vec![$($table.to_string(),)*];
        let groups = groupings.chunks($N);

        let mapped = groups.map(|chunk| {
            let mut tables = chunk.iter().map(ToString::to_string);
            (
                $(
                    replace_expr!(
                        ($table)
                        tables.next().unwrap_or_default()
                    )
                ),*
            )
        });

        let mut builder = Table::builder(mapped);
        builder.remove_columns();
        builder.build().with(Extract::columns(..$N))
    }};
}

I am confident somebody who is good with macros could improve this 2x. However, I was able to get this working to give some nice extra functionality of defining how the tables are divided between rows.

This allows for the following:

parallel_plus!(table_a, table_b, table_c, table_a; 3)
+--------------------------------+---------------------------------------------+-------------------------------------------+
| | name  | age | is_validated | | ┌────────────────────┬─────┬──────────────┐ | .---------------------------------------. |
| |-------|-----|--------------| | │ name               │ age │ is_validated │ | | name             | age | is_validated | |
| | Sam   | 31  | true         | | ├────────────────────┼─────┼──────────────┤ | | Jon Doe          | 255 | false        | |
| | Sarah | 26  | true         | | │ Jack Black         │ 51  │ false        │ | | Mark Nelson      | 13  | true         | |
|                                | ├────────────────────┼─────┼──────────────┤ | | Terminal Monitor | 0   | false        | |
|                                | │ Michelle Goldstein │ 44  │ true         │ | | Adam Blend       | 17  | true         | |
|                                | └────────────────────┴─────┴──────────────┘ | '---------------------------------------' |
+--------------------------------+---------------------------------------------+-------------------------------------------+
| | name  | age | is_validated | |                                             |                                           |
| |-------|-----|--------------| |                                             |                                           |
| | Sam   | 31  | true         | |                                             |                                           |
| | Sarah | 26  | true         | |                                             |                                           |
+--------------------------------+---------------------------------------------+-------------------------------------------+
parallel_plus!(table_a, table_b, table_c, table_a; 2)
+-------------------------------------------+---------------------------------------------+
| | name  | age | is_validated |            | ┌────────────────────┬─────┬──────────────┐ |
| |-------|-----|--------------|            | │ name               │ age │ is_validated │ |
| | Sam   | 31  | true         |            | ├────────────────────┼─────┼──────────────┤ |
| | Sarah | 26  | true         |            | │ Jack Black         │ 51  │ false        │ |
|                                           | ├────────────────────┼─────┼──────────────┤ |
|                                           | │ Michelle Goldstein │ 44  │ true         │ |
|                                           | └────────────────────┴─────┴──────────────┘ |
+-------------------------------------------+---------------------------------------------+
| .---------------------------------------. | | name  | age | is_validated |              |
| | name             | age | is_validated | | |-------|-----|--------------|              |
| | Jon Doe          | 255 | false        | | | Sam   | 31  | true         |              |
| | Mark Nelson      | 13  | true         | | | Sarah | 26  | true         |              |
| | Terminal Monitor | 0   | false        | |                                             |
| | Adam Blend       | 17  | true         | |                                             |
| '---------------------------------------' |                                             |
+-------------------------------------------+---------------------------------------------+
parallel_plus!(table_a, table_b, table_c, table_a; 1)
+---------------------------------------------+
| | name  | age | is_validated |              |
| |-------|-----|--------------|              |
| | Sam   | 31  | true         |              |
| | Sarah | 26  | true         |              |
+---------------------------------------------+
| ┌────────────────────┬─────┬──────────────┐ |
| │ name               │ age │ is_validated │ |
| ├────────────────────┼─────┼──────────────┤ |
| │ Jack Black         │ 51  │ false        │ |
| ├────────────────────┼─────┼──────────────┤ |
| │ Michelle Goldstein │ 44  │ true         │ |
| └────────────────────┴─────┴──────────────┘ |
+---------------------------------------------+
| .---------------------------------------.   |
| | name             | age | is_validated |   |
| | Jon Doe          | 255 | false        |   |
| | Mark Nelson      | 13  | true         |   |
| | Terminal Monitor | 0   | false        |   |
| | Adam Blend       | 17  | true         |   |
| '---------------------------------------'   |
+---------------------------------------------+
| | name  | age | is_validated |              |
| |-------|-----|--------------|              |
| | Sam   | 31  | true         |              |
| | Sarah | 26  | true         |              |
+---------------------------------------------+

Thoughts?

from tabled.

IsaacCloos avatar IsaacCloos commented on June 2, 2024

I am a fan of the test_table! macro 😄

Easier to use than manual. Cleaner. More clear 👍🏻

from tabled.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.