www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can you simplify nested Indexed types?

reply Sergei Nosov <sergei.nosov gmail.com> writes:
Consider, I have the following code:

```
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     ai = indexed(ai, iota(2));

     writeln(ai);
```

Basically, my idea is to apply `indexed` to an array several 
times and have all the intermediaries saved in the same variable. 
The provided code doesn't compile with an error:

```
Error: cannot implicitly convert expression `indexed(ai, 
iota(2))` of type `Indexed!(Indexed!(int[], Result), Result)` to 
`Indexed!(int[], Result)`
```

I wonder, if there's a way to "collapse" or "simplify" the 
`Indexed!(Indexed!(int[], Result), Result)` type to just 
`Indexed!(int[], Result)` ?
Dec 27 2022
next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov wrote:
 Consider, I have the following code:

 ```d
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     //ai = indexed(ai, iota(2));

     writeln(ai);
 ```
I confuse about comment line that I mark... SDB 79
Dec 27 2022
parent reply Sergei Nosov <sergei.nosov gmail.com> writes:
On Tuesday, 27 December 2022 at 15:20:24 UTC, Salih Dincer wrote:
 On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov 
 wrote:
 Consider, I have the following code:

 ```d
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     //ai = indexed(ai, iota(2));

     writeln(ai);
 ```
I confuse about comment line that I mark... SDB 79
Not sure I'll be more helpful, but I'll try to add more details. I have an array and I use `indexed` on it. Conceptually, I now have a second array, but it doesn't exist in memory explicitly - only a function to map indicies from "second array" to "first array" is stored; all the values are stored once - in the "first array". Now, I want to have third array that will do the same trick with the second array. The problem is that the second array is not really an array (but, conceptually, it is an array with random access). If I create a new variable with `auto` as type - obviously, it works. But can I use the same variable I used to store the "second array"? (In the provided code that doesn't work because of the type mismatch).
Dec 27 2022
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/27/22 10:31 AM, Sergei Nosov wrote:
 On Tuesday, 27 December 2022 at 15:20:24 UTC, Salih Dincer wrote:
 On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov wrote:
 Consider, I have the following code:

 ```d
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     //ai = indexed(ai, iota(2));

     writeln(ai);
 ```
I confuse about comment line that I mark... SDB 79
Not sure I'll be more helpful, but I'll try to add more details. I have an array and I use `indexed` on it. Conceptually, I now have a second array, but it doesn't exist in memory explicitly - only a function to map indicies from "second array" to "first array" is stored; all the values are stored once - in the "first array". Now, I want to have third array that will do the same trick with the second array. The problem is that the second array is not really an array (but, conceptually, it is an array with random access). If I create a new variable with `auto` as type - obviously, it works. But can I use the same variable I used to store the "second array"? (In the provided code that doesn't work because of the type mismatch).
So the short answer is no. The long of it is that Indexed is using a source range to give it indexes. In order to save it as the same type, you need to resolve the source of the indexes, when indiexed with the new source range, into the same type, which is not something the library can do. It would have to be specialized to recognize it's using iota as the index range, and then transform the iotas into one iota call. Which isn't impossible, but would be something specialized to this problem. What could be an answer is to have a function that takes 2 iotas, and provides the values as if you were applying the indexes of one to the other, something like: ```d iota!T translate(T)(iota!T orig, iota!T mapping) { // you write this part } ``` Then you can possibly define a function that can convert it properly. -Steve
Dec 27 2022
prev sibling next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov wrote:
 Consider, I have the following code:

 ```d
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     ai = indexed(ai, iota(2));

     writeln(ai);
 ```
Why not use `filter()`, isn't it important to filter out what's in range? ```d import std.algorithm; import std.stdio; import std.range; int[] a = [3, 6, 2, 1, 5, 4, 0]; auto indicies = iota(3); auto ai = a.filter!(e => e >= indicies.front && e <= indicies.back); ai.writeln; // [2, 1, 0] ``` SDB 79
Dec 27 2022
parent Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 27 December 2022 at 16:40:31 UTC, Salih Dincer wrote:
 ```d
 import std.algorithm;
 import std.stdio;
 import std.range;

 int[] a = [3, 6, 2, 1, 5, 4, 0];
 auto indicies = iota(3);
 auto ai = a.filter!(e => e >= indicies.front
                       && e <= indicies.back);
 ai.writeln; // [2, 1, 0]
 ```
Or? ```d indicies.each!((i) => a[i].write(" ")); writeln(); // 3 6 2 ``` SDB 79
Dec 27 2022
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/27/22 07:09, Sergei Nosov wrote:

 Basically, my idea is to apply `indexed` to an array several times and
 have all the intermediaries saved in the same variable.
There may be other ways of achieving the same goal without assigning to the same variable.
 I wonder, if there's a way to "collapse" or "simplify" the
 `Indexed!(Indexed!(int[], Result), Result)` type to just
 `Indexed!(int[], Result)` ?
If what you are looking for is a way of defining a variable for "any InputRange that produces a specific type (size_t in this case)", then there is inputRangeObject, which uses OOP: https://dlang.org/phobos/std_range_interfaces.html#InputRange I have an additional example here: http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObject Ali
Dec 27 2022
parent Sergei Nosov <sergei.nosov gmail.com> writes:
On Tuesday, 27 December 2022 at 16:43:49 UTC, Ali Çehreli wrote:
 On 12/27/22 07:09, Sergei Nosov wrote:
 If what you are looking for is a way of defining a variable for 
 "any InputRange that produces a specific type (size_t in this 
 case)", then there is inputRangeObject, which uses OOP:

   https://dlang.org/phobos/std_range_interfaces.html#InputRange

 I have an additional example here:


 http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObject

 Ali
Thanks, everyone! I guess, this answer is the closest to what I was looking for. Somehow, I missed the range interfaces (and was considering to use `Variant` or smth). It does seem to answer the original question, albeit with layer(s) of indirection. ``` auto indicies = iota(3); RandomAccessFinite!int ai = indexed(a, indicies).inputRangeObject; ai = indexed(ai, iota(2)).inputRangeObject; ``` Still, my gut feel is that some compile-time solution is possible - will, probably, tinker with it for a little more.
 Why not use filter(), isn't it important to filter out what's 
 in range?
That does something different.
 Well, pretty sure this isn't what you meant by "same variable" 
 but since it technically does what you want, I decided to share 
 it: Basically I'm abusing array and this thing might be pretty 
 memory heavy...
Yeah, using arrays is another alternative, but as you mention, it uses more memory and makes index evaluation eager (vs lazy).
Dec 27 2022
prev sibling parent Tejas <notrealemail gmail.com> writes:
On Tuesday, 27 December 2022 at 15:09:11 UTC, Sergei Nosov wrote:
 Consider, I have the following code:

 ```
     auto a = [3, 6, 2, 1, 5, 4, 0];

     auto indicies = iota(3);
     auto ai = indexed(a, indicies);
     ai = indexed(ai, iota(2));

     writeln(ai);
 ```

 Basically, my idea is to apply `indexed` to an array several 
 times and have all the intermediaries saved in the same 
 variable. The provided code doesn't compile with an error:

 ```
 Error: cannot implicitly convert expression `indexed(ai, 
 iota(2))` of type `Indexed!(Indexed!(int[], Result), Result)` 
 to `Indexed!(int[], Result)`
 ```

 I wonder, if there's a way to "collapse" or "simplify" the 
 `Indexed!(Indexed!(int[], Result), Result)` type to just 
 `Indexed!(int[], Result)` ?
Well, pretty sure this isn't what you meant by "same variable" but since it _technically_ does what you want, I decided to share it: Basically I'm abusing `array` and this thing might be pretty memory heavy... ```d import std; void main() { auto a = [3, 6, 2, 1, 5, 4, 0]; auto indices = iota(3); auto ai = indexed(a, indices).array; ai = indexed(ai, iota(2)).array; writeln(ai); // [3, 6] } ```
Dec 27 2022