November 06, 2021

Hi,

It looks to me like A*[] would require extra allocation of memory and ref would not, am I wrong? If so it may be something to consider if relevant for your application.

Thanks.

November 06, 2021

On Saturday, 6 November 2021 at 04:28:05 UTC, Ali Çehreli wrote:

>

On 11/5/21 5:43 PM, Andrey Zherikov wrote:

In case others want to work, here are the modules that need to be imported:

import std.algorithm;
import std.range;
import std.stdio;

>

struct A {}
struct B
{
A[] ar = [A.init];
size_t[] idx = [0];

I don't know why but those initial values are the reason for the problem. It works without them.

get() will return nothing in this case. But I can make them non empty in another way:

import std;

struct A {}
struct B
{
    A[] ar;
    size_t[] idx;

    A*[] get()
    {
        return idx.map!((idx) => &ar[idx]).array;
    }
}

auto foo()
{
    B b;
    b.ar ~= A.init;
    b.idx ~= 0;
    return b.get();
}

void main()
{
    writeln(foo());
    pragma(msg, foo());
}

Some one can complain that foo() returns pointers that are not available in CTFE but remember that the real code is more complex and foo() cam be return just length (return b.get().length;) having the same result.

Basically I have a collection of data (A[] ar), different addressing through the indexes (multiple size_t[] idx) and I want to manipulate these objects through indexes. If there is another way to achieve the same in CFTE, I'd like to hear.

November 06, 2021
On 11/6/21 5:05 AM, Andrey Zherikov wrote:

> Some one can complain that `foo()` returns pointers that are not
> available in CTFE but remember that the real code is more complex and
> `foo()` cam be return just length (`return b.get().length;`) having the
> same result.

I think the error you got is a bug and should be reported because it does not make sense:

  Error: couldn't find field `ar` of type `A[]` in `MapResult([0LU], null)`

> Basically I have a collection of data (`A[] ar`), different addressing
> through the indexes (multiple `size_t[] idx`) and I want to manipulate
> these objects through indexes. If there is another way to achieve the
> same in CFTE, I'd like to hear.

Have you considered std.range.indexed, which should at least cover the case of accessing:

  https://dlang.org/phobos/std_range.html#indexed

For changing values, how about passing in a function pointer e.g. a lambda? The following one takes A and returns A but you can have a different approach where the function takes by 'ref A' and modifies its parameter:

  void set(A function(A) func) {
    foreach (i; idx) {
      ar[i] = func(ar[i]);
    }
  }

Can you give a little more context for others to come up with a better answer?

Ali

November 06, 2021

On Saturday, 6 November 2021 at 13:57:47 UTC, Ali Çehreli wrote:

>

Have you considered std.range.indexed, which should at least cover the case of accessing:

https://dlang.org/phobos/std_range.html#indexed

I don't need to iterate over whole collection, but subset of it.

>

Can you give a little more context for others to come up with a better answer?

I have a CLI-parsing library that creates a set of argument objects based on UDAs. They are stored in array right now. I want to introduce some grouping having something like struct Group { size_t[] args; } but face the problem of addressing the objects. As of now I need to be able to iterate over the arguments within a group as well as those that satisfy some condition.

November 06, 2021
On 11/6/21 8:57 AM, Andrey Zherikov wrote:
> On Saturday, 6 November 2021 at 13:57:47 UTC, Ali Çehreli wrote:
>> Have you considered std.range.indexed, which should at least cover the
>> case of accessing:
>>
>>   https://dlang.org/phobos/std_range.html#indexed
>
> I don't need to iterate over whole collection, but subset of it.

'indexed' does not iterate the collection; just the ones that are in the index array. For example, if you have 2 size_t elements in the index array, 'indexed' will touch just two elements.

> As of now I need to be able to iterate over the arguments
> within a group as well as those that satisfy some condition.

It turns out 'indexed' provides access by reference; so you can even mutate the elements:

import std.algorithm;
import std.range;
import std.stdio;

void main() {
  int[] numbers = [ 0, 1, 2, 3, 4, 5 ];

  size_t[] specials = [ 1, 5 ];
  size_t[] moreSpecials = [ 2, 3, 4 ];

  numbers.indexed(specials).each!((ref n) => n *= 10);
  writeln(numbers);
}

The output shows elements 1 and 5 are multiplied by 10:

[0, 10, 2, 3, 4, 50]

I am happy with that solution. ;)

Of course you can use foreach instead of 'each' and apply some filtering condition, etc.

Ali


1 2
Next ›   Last »