Re: How to obtain Variant underlying type?
On Monday, 11 July 2022 at 06:59:32 UTC, anonymouse wrote: I did search for a better solution and came across... https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html I like it! It's been a good collaboration... ```d import std.variant; auto generate(T)(size_t x, size_t y) { T[][] result; ubyte[] arr = new ubyte[x * y * T.sizeof]; size_t m = y * T.sizeof; foreach (i; 0 .. x) { size_t n = i * m; result ~= cast(T[])arr[n .. n + m]; } return result; } size_t[] shape(Variant v) { typeof(return) dims; while (cast(TypeInfo_Array) v.type !is null) { dims ~= v.length; v = v[0]; } if (!dims.length && v.length) { dims ~= v.length; dims ~= 0; } return dims; } void main() { foreach(x; 1..100) { foreach(y; 1..100) { auto test = Variant(generate!int(x, y)); assert(shape(test) == [x, y]); } } } ``` SDB@79
Re: How to obtain Variant underlying type?
On Monday, 11 July 2022 at 05:41:40 UTC, jfondren wrote: Oh, sorry. I didn't defend the code in any way because I assumed that the exceptional design would be seen as obviously bad (and that someone else would dig harder in order to find a better solution). And you were right. I did search for a better solution and came across [1]. Although I was having some issues adapting it for my use case, Paul Backus' follow-up clarified the issue. This is what my naive brain led to before reading this response. ```d size_t[] shape(Variant v) { typeof(return) dims; while(cast(TypeInfo_Array) v.type !is null) { dims ~= v.length; v = v[0]; } if(!dims.length && v.length) { dims ~= v.length; dims ~= 0; } return dims; } ``` Didn't see the bugs that would occur when a scalar or empty array was passed because I hadn't tested for them. if (!v.length) break; Pure gold! Bugs are eliminated, and the code is shorter. Thank you. --anonymouse [1] https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html
Re: How to obtain Variant underlying type?
On Sunday, 10 July 2022 at 19:14:34 UTC, Paul Backus wrote: For reference, this is the more correct way: ```d while (cast(TypeInfo_Array) v.type !is null) { Variant elem = v[0]; // etc. } ``` Hard to blame anyone for not coming up with that on their first try, especially since `TypeInfo_Array` is not even documented--you have to read the source of `object.d` to find out about it. I honestly cannot say why but I was having a problem using this earlier. After several hours of frustration, I rebooted the computer, went for a run, came back, and tried again. It works!!! Thank you very much. --anonymouse
Re: How to obtain Variant underlying type?
On Monday, 11 July 2022 at 03:17:33 UTC, anonymouse wrote: On Sunday, 10 July 2022 at 18:31:46 UTC, drug007 wrote: I'd like to say that using of exception to break loop is really bad. Exception is exceptional thing but in the case above the exception is ordinary completion of the loop happens on regular basis. Don't do that. Thanks for the advice. Lesson learned. --anonymouse Oh, sorry. I didn't defend the code in any way because I assumed that the exceptional design would be seen as obviously bad (and that someone else would dig harder in order to find a better solution). The TypeInfo_Array fix breaks the last assertion of those unit tests, though. This works: ```d import std.variant : Variant; size_t[] shape(Variant v) { size_t[] s; while (cast(TypeInfo_Array) v.type !is null && v.length > 0) { Variant elem = v[0]; s ~= v.length; v = elem; } return s; } ``` Although, that last assertion really is debatable. Languages like APL would read it as having a shape of [2, 0]: ```d import std.variant : Variant; size_t[] shape(Variant v) { size_t[] s; while (cast(TypeInfo_Array) v.type !is null) { s ~= v.length; if (!v.length) break; v = v[0]; } return s; } unittest { assert([3, 1] == [[1], [2], [3]].Variant.shape); assert([2, 1] == [[1], [2]].Variant.shape); assert([2, 2] == [[1, 0], [2, 0]].Variant.shape); assert([2] == [1, 2].Variant.shape); assert([] == 2.Variant.shape); assert([2, 0] == [[], []].Variant.shape); // irregularity not checked assert([2, 2] == [[1, 0], [2]].Variant.shape); } ```
Re: How to obtain Variant underlying type?
On Sunday, 10 July 2022 at 18:31:46 UTC, drug007 wrote: I'd like to say that using of exception to break loop is really bad. Exception is exceptional thing but in the case above the exception is ordinary completion of the loop happens on regular basis. Don't do that. Thanks for the advice. Lesson learned. --anonymouse
Re: How to obtain Variant underlying type?
On Sunday, 10 July 2022 at 18:31:46 UTC, drug007 wrote: On 7/10/22 20:26, anonymouse wrote: On Sunday, 10 July 2022 at 06:26:37 UTC, jfondren wrote: ```d import std.variant : Variant; size_t[] shape(Variant v) { import std.variant : VariantException; size_t[] s; try { while (true) { Variant elem = v[0]; s ~= v.length; v = elem; } } catch (VariantException e) { return s; } } ``` Thank you very much. I'd like to say that using of exception to break loop is really bad. Exception is exceptional thing but in the case above the exception is ordinary completion of the loop happens on regular basis. Don't do that. For reference, this is the more correct way: ```d while (cast(TypeInfo_Array) v.type !is null) { Variant elem = v[0]; // etc. } ``` Hard to blame anyone for not coming up with that on their first try, especially since `TypeInfo_Array` is not even documented--you have to read the source of `object.d` to find out about it.
Re: How to obtain Variant underlying type?
On Sunday, 10 July 2022 at 06:26:37 UTC, jfondren wrote: ```d import std.variant : Variant; size_t[] shape(Variant v) { import std.variant : VariantException; size_t[] s; try { while (true) { Variant elem = v[0]; s ~= v.length; v = elem; } } catch (VariantException e) { return s; } } ``` Thank you very much.
Re: How to obtain Variant underlying type?
On Saturday, 9 July 2022 at 23:04:20 UTC, anonymouse wrote: On Saturday, 9 July 2022 at 14:46:36 UTC, Adam D Ruppe wrote: Impossible; Variant's type is only known at runtime, and this would require compile time knowledge. Hmmm. Okay, thanks. What I really need to know is how many dimensions an array has and the total elements per dimension so that I can create temporary storage for it later. this(T)(T a) in(imported!"std.traits".isDynamic!T) { data = a; // data is of type Variant shape = [a.length, {?, ...}]; // what's the best way to deterine? } Thanks, --anonymouse ```d import std.variant : Variant; size_t[] shape(Variant v) { import std.variant : VariantException; size_t[] s; try { while (true) { Variant elem = v[0]; s ~= v.length; v = elem; } } catch (VariantException e) { return s; } } unittest { assert([3, 1] == [[1], [2], [3]].Variant.shape); assert([2, 1] == [[1], [2]].Variant.shape); assert([2, 2] == [[1, 0], [2, 0]].Variant.shape); assert([2] == [1, 2].Variant.shape); assert([] == 2.Variant.shape); // irregularity not checked assert([2, 2] == [[1, 0], [2]].Variant.shape); // arguably should be [2, 0] assert([2] == [[], []].Variant.shape); } ```
Re: How to obtain Variant underlying type?
On Saturday, 9 July 2022 at 14:46:36 UTC, Adam D Ruppe wrote: Impossible; Variant's type is only known at runtime, and this would require compile time knowledge. Hmmm. Okay, thanks. What I really need to know is how many dimensions an array has and the total elements per dimension so that I can create temporary storage for it later. this(T)(T a) in(imported!"std.traits".isDynamic!T) { data = a; // data is of type Variant shape = [a.length, {?, ...}]; // what's the best way to deterine? } Thanks, --anonymouse
Re: How to obtain Variant underlying type?
On Saturday, 9 July 2022 at 14:36:44 UTC, anonymouse wrote: auto vb = v.base; // what should I put here to achieve the following: typeof(vb); // int[][] Impossible; Variant's type is only known at runtime, and this would require compile time knowledge.