tdwright / contabs

Simple yet flexible tables for console apps.
MIT License
54 stars 20 forks source link

Computed columns #53

Closed Chandler-Davidson closed 6 years ago

Chandler-Davidson commented 6 years ago

Added the ability to add generated columns, necessary XML comments, as well as unit tests for such.

Currently, there are two overloaded methods so that users can create a column operating on a single operand or two operands. Any type is valid and can be created using inline lambda expressions or local functions. Usage looks like such:

table.Columns.AddGeneratedColumn<DateTime, double>(    // <input type, output type>
    (start, end) => (end - start).TotalDays,    // Expression
    "Total Days",    // New Column Name
    table.Columns[0], table.Columns["End"]);    // Select Columns

Added a new method that supports a List input for several operands. Usage looks like such:


table.Columns.AddGeneratedColumnFromRange<int, int>(
    (costs) => costs.Sum(),
    "Total",
    table.Columns);
tdwright commented 6 years ago

Hi @Chandler-Davidson!

Thanks for this contribution.

Apologies for the radio silence recently - I've been crazy busy with preparations to relocate my family.

Anyway, from a superficial reading, this looks great. I'll have a proper play with it next week hopefully.

Tom

Chandler-Davidson commented 6 years ago

No worries! I'm pretty happy with how it came out, good luck with the move.

Chandler-Davidson commented 6 years ago

Any updates? Thanks!

tdwright commented 6 years ago

Hi @Chandler-Davidson. Greetings from Malaysia.

Apologies for the delay - I've been off grid.

Superficially, this looks really good. Am just going to have a play around with this and see how it feels. It's a pretty big piece of functionality IMHO, so want to make sure it's right.

Tom

Chandler-Davidson commented 6 years ago

Just pushed a few minor changes to this branch, nothing more than documentation and renaming of variables. I've looked through several possible rewrites of the proposed methods and have not come up with any significant changes without some major costs.

Current Method

Currently, the call to generate columns is explicit and verbose. The user has to set their expected input/output types, overloaded functions for the quantity of columns, and is limited to a single input type.

Dynamic Methods

An alternate route to explore are Dynamic Methods and seem on topic for what we are trying to accomplish. This would allow for more robust typing, easier testing, and a more generic function call thanks to the params keyword.

table.Columns.AddGeneratedColumn<float>(Sum, "Sum", t.Columns["A"], t.Columns[1]);

There are a few costs of dynamic methods as they're very slow and I have yet found a way to 'unpack' the parameters from a list individual parameters.

Conclusion

Take a look at my changes and let me know where we can go from here. I don't mind if anyone else has any proposed changes.

tdwright commented 6 years ago

Hi @Chandler-Davidson,

Thanks for doing such detailed research. I had a hunch that it would be a challenge to make it more flexible without being horrendously complicated. As I said before, we're maxing out what can be done with generics and reflection whilst trying to preserve type-safety.

I'm going to accept these changes now and have a little fiddle myself.

Thanks for your continued contributions and for your patience whilst I was incommunicado!

Tom