Comments (7)
Wow, combining the good parts of different solutions to get the best one. I feel proud for being treated like that, thank you! 😄
Now that I think of it, most of the pros and cons I've shown stem from the question "How to deliver the desired feature with breaking API as less as possible, ideally not breaking at all, at the same time trying not to sacrifice raw performance?" So far I only considered dynamic dispatch + enum, because it can be done implicitly albeit giving up on effectiveness. But if genericity is worth going all out, then I'm on it!
from prettytable-rs.
Hi !
I've read this very quickly on my phone. I need to read again more carefully, but it seems very interresting and legit. I'm not sure which of the 3 propositions I prefer. As you said, they all have their pros and cons. Offerring the maximum flexibility to library users would probably be the best.
By the way, regarding the cons around the Enum-based solution, I think we could implement the From
conversion trait on the enum and use it in the cell!
macro instead of implementing a macro for each variant.
Also, regarding the inflexibility, we could still have a variant for generic trait objects. Like some kind of mix with your 3 proposals.
Just throwing ideas. I'll study your proposal more carefully later today.
Thanks
from prettytable-rs.
From
really looks good to me (I've forgotten the obvious example of try!
).
Did I get it right that by "a variant for generic trait objects" you meant something like CellContentBox::Other(Box<CellContent>)
? If it really is... Well, it doesn't look elegant, but seems like a viable compromise.
Ah, and macros in all 3 cases can work without modifying external API. \o/
from prettytable-rs.
Yes,that's what I meant, but I'm agree it's not really elegant.
I've been thinking on this on the way back to home, and maybe we can mix your 3 proposals into 1, and let the library user choose.
Let me explain:
Regarding your first proposal, the plan is to define something like
struct Table<T: CellContent> { ... }
right ?
So by implementing the CellContent
over appropriate types we can have
Table<Vec<String>>
Table<Table<Vec<String>>
// An so on ...
As you said, we would have to spread the type accross the entire API, but I'm not fully agree when you say we would be locked to one single type. In fact we should be able to write something like
impl <T> CellContent for Box<T> where T: CellContent + ?Sized { ... }
// Then use
Table<Box<CellContent>>
This would enable statically AND dynamically dispatched trait-based solution. Merging together your proposals 1 an 2.
The library user would decide which kind of usage is more approriate to the situation.
We can also hide it behind a type like
pub type BoxTable = Table<Box<CellContent>>;
And finally, your third proposal can also join the party since the enum can also implement CellContent
. With it, the lib user would be able to opt for a "multi-typed content" but statically dispatched solution.
from prettytable-rs.
Current implementation progress:
-
Static dispatch (only)
Converting
Table
toTable<T>
and usingVec<String>
as a type parameter works as it worked before, although with a small cheat: I had to createstruct CellLines { lines: Vec<String>, }
to implement
impl<T: ToString> From<T> for CellLines { fn from(value: T) -> CellLines { CellLines { lines: value.to_string().lines().map(str::to_owned).collect() } } }
for convenience, so the actual table is
Table<CellLines>
. Also this means inner tables are converted to strings, so no custom behaviour available. -
Dynamic dispatch (only)
Given
impl<T: CellContent> From<T> for Box<CellContent> { fn from(content: T) -> Box<CellContent> { Box::new(content) } }
I wanted to do:
impl Cell { fn new<T, U>(value: U) -> Cell where T: From<U> + CellContent { Cell { content: Box::new(T::from(value)) } } }
but this definition is ambiguous in
T
, so I had to make a more strict one:impl Cell { fn new<T: CellContent>(content: T) -> Cell { Cell { content: Box::new(content) } } }
With this we have to use, for example,
Cell::new(CellLines::from("many\nlines"))
instead ofCell::new("many\nlines")
orCell::new(From::from("many\nlines"))
.Cell::new(table)
still works though.As another solution, I tried
impl<T: ToString> From<T> for Box<CellContent> { fn from(value: T) -> Box<CellContent> { Box::new(CellLines::from(value)) // uses From<T> for CellLines above } }
However, this definition along with
impl From<Table> for Box<CellContent>
results in conflicting implementations becauseTable
implements bothCellContent
andToString
.This is a blocker issue for me, since I can't think of any other way other than
impl
specialization, which is not even done yet. As a result, it will to be difficult to make a catch-allcell!
implementation. I hope there can be other working solutions which retain a user-friendly API. -
Enum
Practically the same issue as with dynamic dispatch, only with
enum CellContentBox
presented in the proposal.
from prettytable-rs.
Hi ! Sorry for the late reply, I've been quite busy this week. I havent had time yet to start experimenting around this redesign. I'll give it a look ASAP. In the meantime could you share your code ?
from prettytable-rs.
The code is here: https://github.com/hcpl/prettytable-rs/tree/cell-redesign.
One notable API change to consider there is allowing table!
and cell!
to accept a type hint argument (though couldn't figure out how to do this for row!
because of its vector-like syntax).
from prettytable-rs.
Related Issues (20)
- Using more than one character as separator
- term has security warning, please update HOT 1
- Question: Slice Usage With Row Macro
- Support styling options / colors for borders and separators HOT 2
- Crash due to subtract with overflow HOT 4
- Allow skipping line separators HOT 2
- Mark crate as `deprecated` on crates.io HOT 1
- TableSlice::print_tty() should not panic on I/O errors HOT 1
- output of a table to a string with styles -- is it possible? HOT 5
- Some suggestions to simplify the code
- Replace atty dependency in prettytable-rs due to RUSTSEC-2021-0145 HOT 2
- force casting Vec<T> to &[T] in Table::AsRef is causing trouble HOT 12
- Release 0.10.0 HOT 2
- Make Color optional HOT 1
- Release x.y.z
- Apply dynamic styles to nested table HOT 4
- Could we get some form of Format Macro? HOT 1
- Display Train over Table Object
- .printhtml() method doesnt insert table headers (titles) correctly HOT 2
- Unexpected `FromIterator<Utf8Char> for Vec<u8>` import by just importing prettytable-rs
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from prettytable-rs.