digitalmars.D.learn - Runtime heterogeneous collections?
- Steven O (21/21) Jan 16 2019 I want to create a heterogeneous collection of red-black trees,
- Neia Neutuladh (10/12) Jan 16 2019 RedBlackTree!int and RedBlackTree!string are entirely different types
- Dukc (5/11) Jan 17 2019 3. Use an union. However, only do this if you always know from
- Jonathan M Davis (12/23) Jan 17 2019 Variant types are really just user-friendly wrappers around unions. So,
- Steven Schveighoffer (17/43) Jan 18 2019 A variant is not a union. Algebraic is a union, but Variant can hold ANY...
- Alex (4/16) Jan 18 2019 In this case, I would say Phobos lacks an appropriate interface
- Steven Schveighoffer (6/23) Jan 18 2019 But what is the common interface between those 2 types? Even in
- Neia Neutuladh (3/7) Jan 18 2019 .empty(), .clear(), .length(), and .toString(sink, formatspec). Which is...
- Steven Schveighoffer (5/14) Jan 18 2019 Yeah, I didn't bother with any of those as base interfaces. Probably the...
- Alex (4/17) Jan 18 2019 Aha... I see... all important methods are templated on the
- Seb (4/18) Jan 17 2019 As the OP is most likely looking for Variant, let me link to it:
- Steven O (7/7) Jan 19 2019 I'd like to thank everyone for their help! I was finally able to
- Kagamin (7/12) Jan 18 2019 alias Rec_type1 = Tuple!(int, "x", int, "y", int, "z");
I want to create a heterogeneous collection of red-black trees, and I can't seem to figure out if it's possible. I can easily do: import std.container.rbtree; import std.typecons; void main() { alias Rec_type = Tuple!(int, "x", int, "y", int, "z"); RedBlackTree!Rec_type[1] test; } That works great, but I can only add red-black trees of Rec_type. What if I want the collection of red-black trees to be different? So if you printed out the collection of red-black trees you'd see something akin to: // Formatted for easier reading [ RedBlackTree([Tuple!(int, "x", int, "y", string, "z")(1, 2, "abc")]), RedBlackTree([Tuple!(int, "x", int, "y", int, "z")(1, 2, 3)]) ] Is it possible to do this?
Jan 16 2019
On Thu, 17 Jan 2019 02:21:21 +0000, Steven O wrote:I want to create a heterogeneous collection of red-black trees, and I can't seem to figure out if it's possible.RedBlackTree!int and RedBlackTree!string are entirely different types (they just happen to be generated from the same template). There are two reasonable ways of doing things: 1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types. You can use this technique either with the collection types themselves or with the value types.
Jan 16 2019
On Thursday, 17 January 2019 at 02:27:20 UTC, Neia Neutuladh wrote:1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types.3. Use an union. However, only do this if you always know from outside what type of data is stored in each node. If you need to memoize the type of data for each node, better resort to 1. or 2.
Jan 17 2019
On Thursday, January 17, 2019 1:21:41 AM MST Dukc via Digitalmars-d-learn wrote:On Thursday, 17 January 2019 at 02:27:20 UTC, Neia Neutuladh wrote:Variant types are really just user-friendly wrappers around unions. So, pedantically, using a variant type such as Variant or Albegbraic and using a union are fundamentally the same thing, though obviously, the actual usage in terms of the code that you write is not the same, since if you use a union directly, you have to deal with the union directly (including figuring out how to know which type the union currently holds), whereas with a Variant, you're using its API rather than dealing with the union directly. In general, it's probably better to use Variant rather than union simply because Variant deals with the type safety for you. - Jonathan M Davis1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types.3. Use an union. However, only do this if you always know from outside what type of data is stored in each node. If you need to memoize the type of data for each node, better resort to 1. or 2.
Jan 17 2019
On 1/17/19 11:06 PM, Jonathan M Davis wrote:On Thursday, January 17, 2019 1:21:41 AM MST Dukc via Digitalmars-d-learn wrote:A variant is not a union. Algebraic is a union, but Variant can hold ANY type, even types your code doesn't know about. To answer the OP, what he wants is an array of different RedBlackTrees. Since RedBlackTree is a class, his code is not far off from something that works. This does compile, and produces an Object[]: auto arr = [ redBlackTree(Tuple!(int, "x", int, "y", string, "z")(1, 2, "abc")), redBlackTree(Tuple!(int, "x", int, "y", int, "z")(1, 2, 3)) ]; Then you have to cast each object into it's appropriate type to use it. That is not as easy, as you have to know the exact instantiation of tree type. In this case, you are better off using a union, or an Algebraic as your array element type. If you use something like https://code.dlang.org/packages/taggedalgebraic it could be quite usable. -SteveOn Thursday, 17 January 2019 at 02:27:20 UTC, Neia Neutuladh wrote:Variant types are really just user-friendly wrappers around unions. So, pedantically, using a variant type such as Variant or Albegbraic and using a union are fundamentally the same thing, though obviously, the actual usage in terms of the code that you write is not the same, since if you use a union directly, you have to deal with the union directly (including figuring out how to know which type the union currently holds), whereas with a Variant, you're using its API rather than dealing with the union directly. In general, it's probably better to use Variant rather than union simply because Variant deals with the type safety for you.1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types.3. Use an union. However, only do this if you always know from outside what type of data is stored in each node. If you need to memoize the type of data for each node, better resort to 1. or 2.
Jan 18 2019
On Friday, 18 January 2019 at 13:31:28 UTC, Steven Schveighoffer wrote:To answer the OP, what he wants is an array of different RedBlackTrees. Since RedBlackTree is a class, his code is not far off from something that works. This does compile, and produces an Object[]: auto arr = [ redBlackTree(Tuple!(int, "x", int, "y", string, "z")(1, 2, "abc")), redBlackTree(Tuple!(int, "x", int, "y", int, "z")(1, 2, 3)) ]; Then you have to cast each object into it's appropriate type to use it. That is not as easy, as you have to know the exact instantiation of tree type.In this case, I would say Phobos lacks an appropriate interface definition, what do you think?
Jan 18 2019
On 1/18/19 9:58 AM, Alex wrote:On Friday, 18 January 2019 at 13:31:28 UTC, Steven Schveighoffer wrote:But what is the common interface between those 2 types? Even in Dcollections, where RedBlackTree came from, there was no interfaces that didn't specify the type they were dealing with. In other words, there is no common interface for sets of 2 different types. -SteveTo answer the OP, what he wants is an array of different RedBlackTrees. Since RedBlackTree is a class, his code is not far off from something that works. This does compile, and produces an Object[]: auto arr = [ redBlackTree(Tuple!(int, "x", int, "y", string, "z")(1, 2, "abc")), redBlackTree(Tuple!(int, "x", int, "y", int, "z")(1, 2, 3)) ]; Then you have to cast each object into it's appropriate type to use it. That is not as easy, as you have to know the exact instantiation of tree type.In this case, I would say Phobos lacks an appropriate interface definition, what do you think?
Jan 18 2019
On Fri, 18 Jan 2019 10:07:41 -0500, Steven Schveighoffer wrote:But what is the common interface between those 2 types? Even in Dcollections, where RedBlackTree came from, there was no interfaces that didn't specify the type they were dealing with. In other words, there is no common interface for sets of 2 different types..empty(), .clear(), .length(), and .toString(sink, formatspec). Which is kind of anemic. Might as well use Object.
Jan 18 2019
On 1/18/19 10:10 AM, Neia Neutuladh wrote:On Fri, 18 Jan 2019 10:07:41 -0500, Steven Schveighoffer wrote:Yeah, I didn't bother with any of those as base interfaces. Probably the most basic interface for dcollections was Iterator(V): https://github.com/schveiguy/dcollections/blob/master/dcollections/model/Iterator.d#L40-L58 -SteveBut what is the common interface between those 2 types? Even in Dcollections, where RedBlackTree came from, there was no interfaces that didn't specify the type they were dealing with. In other words, there is no common interface for sets of 2 different types...empty(), .clear(), .length(), and .toString(sink, formatspec). Which is kind of anemic. Might as well use Object.
Jan 18 2019
On Friday, 18 January 2019 at 15:07:41 UTC, Steven Schveighoffer wrote:On 1/18/19 9:58 AM, Alex wrote:Aha... I see... all important methods are templated on the element type... hmm.On Friday, 18 January 2019 at 13:31:28 UTC, Steven Schveighoffer wrote:But what is the common interface between those 2 types? Even in Dcollections, where RedBlackTree came from, there was no interfaces that didn't specify the type they were dealing with. In other words, there is no common interface for sets of 2 different types. -Steve[...]In this case, I would say Phobos lacks an appropriate interface definition, what do you think?
Jan 18 2019
On Thursday, 17 January 2019 at 02:27:20 UTC, Neia Neutuladh wrote:On Thu, 17 Jan 2019 02:21:21 +0000, Steven O wrote:As the OP is most likely looking for Variant, let me link to it: https://dlang.org/phobos/std_variant.html#VariantI want to create a heterogeneous collection of red-black trees, and I can't seem to figure out if it's possible.RedBlackTree!int and RedBlackTree!string are entirely different types (they just happen to be generated from the same template). There are two reasonable ways of doing things: 1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types. You can use this technique either with the collection types themselves or with the value types.
Jan 17 2019
I'd like to thank everyone for their help! I was finally able to do what I'd like. I didn't end up using a variant, but maybe there's a better way to do what I want using it, and I just couldn't figure it out. Here's the solution I finally came up with: https://run.dlang.io/is/GdDDBp If anyone has any better solutions I'm all ears!
Jan 19 2019
On Thursday, 17 January 2019 at 02:21:21 UTC, Steven O wrote:void main() { alias Rec_type = Tuple!(int, "x", int, "y", int, "z"); RedBlackTree!Rec_type[1] test; }alias Rec_type1 = Tuple!(int, "x", int, "y", int, "z"); alias Rec_type2 = Tuple!(int, "x", int, "y", string, "z"); Tuple!(RedBlackTree!Rec_type1, "x", RedBlackTree!Rec_type2, "z") test; Similar questions were asked before, usually such heterogeneous collections are not the best solution to the problem at hand.
Jan 18 2019