Re: How to return a reference to structs?

2021-11-06 Thread Ali Çehreli via Digitalmars-d-learn

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




Re: How to return a reference to structs?

2021-11-06 Thread Andrey Zherikov via Digitalmars-d-learn

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](https://github.com/andrey-zherikov/argparse) that 
creates a set of argument objects based on UDAs. They are [stored 
in 
array](https://github.com/andrey-zherikov/argparse/blob/master/source/argparse.d#L436) 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.


Re: How to return a reference to structs?

2021-11-06 Thread Ali Çehreli via Digitalmars-d-learn

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



Re: How to return a reference to structs?

2021-11-06 Thread Andrey Zherikov via Digitalmars-d-learn

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:


```d
import std;

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

A*[] get()
{
return idx.map!((idx) => [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.


Re: How to return a reference to structs?

2021-11-06 Thread data pulverizer via Digitalmars-d-learn

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.



Re: How to return a reference to structs?

2021-11-05 Thread Ali Çehreli via Digitalmars-d-learn

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.


>
>  A*[] get()
>  {
>  return idx.map!((idx) => [idx]).array;  // Error: couldn't
> find field `ar` of type `A[]` in `MapResult([0LU], null)`
>  }
> }
>
> auto foo()
> {
>  B b;
>  return b.get();
> }
>
> void main()
> {
>  writeln(foo());   // This works
>  pragma(msg, foo());   // This doesn't work
> }

Ali



Re: How to return a reference to structs?

2021-11-05 Thread Andrey Zherikov via Digitalmars-d-learn

On Friday, 5 November 2021 at 20:13:02 UTC, Andrey Zherikov wrote:

On Friday, 5 November 2021 at 19:49:50 UTC, Ali Çehreli wrote:
Indexes are typed as size_t, which is ulong for 64-bit and 
uint for 32-bit. If idx elements were indeed indexes, it 
should have been typed as size_t:


size_t[] idx = [1,3,4];  // <-- Here



Ah, good point. Thanks!


Adding a bit of CTFE:
```d
struct A {}
struct B
{
A[] ar = [A.init];
size_t[] idx = [0];

A*[] get()
{
return idx.map!((idx) => [idx]).array;  // Error: 
couldn't find field `ar` of type `A[]` in `MapResult([0LU], null)`

}
}

auto foo()
{
B b;
return b.get();
}

void main()
{
writeln(foo());   // This works
pragma(msg, foo());   // This doesn't work
}
```

How to make this work?


Re: How to return a reference to structs?

2021-11-05 Thread Andrey Zherikov via Digitalmars-d-learn

On Friday, 5 November 2021 at 19:49:50 UTC, Ali Çehreli wrote:
Indexes are typed as size_t, which is ulong for 64-bit and uint 
for 32-bit. If idx elements were indeed indexes, it should have 
been typed as size_t:


size_t[] idx = [1,3,4];  // <-- Here



Ah, good point. Thanks!


Re: How to return a reference to structs?

2021-11-05 Thread Ali Çehreli via Digitalmars-d-learn

On 11/5/21 11:44 AM, kdevel wrote:
> On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov wrote:
>> I have the following code example:
>
> [...]
>
>> A[5] a;
>> ulong[] idx = [1,3,4];
>
> [...]
>
>> return idx.map!(_ => a[_]);
>
> How can one make the type of idx's elements portable (compile with -m32
> to see what the problem is)?

Indexes are typed as size_t, which is ulong for 64-bit and uint for 
32-bit. If idx elements were indeed indexes, it should have been typed 
as size_t:


import std.algorithm;
import std.stdio;

struct A{}

A[5] a;
size_t[] idx = [1,3,4];  // <-- Here

auto get()
{
return idx.map!(_ => a[_]);
}

void main() {
  foreach(i; 0 .. a.length)
write([i], " ");
  writeln;

  foreach(ref b; get())
write(, " ");
  writeln;
}

Ali



Re: How to return a reference to structs?

2021-11-05 Thread kdevel via Digitalmars-d-learn
On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov 
wrote:

I have the following code example:


[...]


A[5] a;
ulong[] idx = [1,3,4];


[...]


return idx.map!(_ => a[_]);


How can one make the type of idx's elements portable (compile 
with -m32 to see what the problem is)? This seems to be an 
surprisingly nontrivial issue at least in C [1].


[1] 



Re: How to return a reference to structs?

2021-11-04 Thread Paul Backus via Digitalmars-d-learn
On Thursday, 4 November 2021 at 18:21:06 UTC, Andrey Zherikov 
wrote:

On Thursday, 4 November 2021 at 13:03:54 UTC, Paul Backus wrote:


Have the lambda return by reference:

```d
auto get()
{
return idx.map!(ref (i) => a[i]);
}
```


Making this example a bit complex: I want `get` to return 
additional data to the reference. How should I change the 
lambda then?

```d
auto get()
{
return idx.map!(ref (i) => tuple(a[i], i)); // return ref 
and index for simplicity

}
```


Since there are no such thing as `ref` variables in D, you can't 
store a reference inside a tuple. So in this case, you will have 
to use a pointer:


```d
auto get()
{
return idx.map!((i) => tuple([i], i));
}
```


Re: How to return a reference to structs?

2021-11-04 Thread Andrey Zherikov via Digitalmars-d-learn

On Thursday, 4 November 2021 at 13:03:54 UTC, Paul Backus wrote:
On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov 
wrote:

I have the following code example:

```d
struct A{}

A[5] a;
ulong[] idx = [1,3,4];

auto get()
{
return idx.map!(_ => a[_]);
}

foreach(i; 0 .. a.length)
write([i], " ");
writeln;

foreach(ref b; get())
write(, " ");
writeln;
```

How can I change `get` function so it returns the references 
to the content in `a`?


Have the lambda return by reference:

```d
auto get()
{
return idx.map!(ref (i) => a[i]);
}
```


Making this example a bit complex: I want `get` to return 
additional data to the reference. How should I change the lambda 
then?

```d
auto get()
{
return idx.map!(ref (i) => tuple(a[i], i)); // return ref and 
index for simplicity

}
```


Re: How to return a reference to structs?

2021-11-04 Thread Andrey Zherikov via Digitalmars-d-learn

On Thursday, 4 November 2021 at 13:03:54 UTC, Paul Backus wrote:

Have the lambda return by reference:

```d
auto get()
{
return idx.map!(ref (i) => a[i]);
}
```


That works, thanks!


Re: How to return a reference to structs?

2021-11-04 Thread Paul Backus via Digitalmars-d-learn
On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov 
wrote:

I have the following code example:

```d
struct A{}

A[5] a;
ulong[] idx = [1,3,4];

auto get()
{
return idx.map!(_ => a[_]);
}

foreach(i; 0 .. a.length)
write([i], " ");
writeln;

foreach(ref b; get())
write(, " ");
writeln;
```

How can I change `get` function so it returns the references to 
the content in `a`?


Have the lambda return by reference:

```d
auto get()
{
return idx.map!(ref (i) => a[i]);
}
```


How to return a reference to structs?

2021-11-04 Thread Andrey Zherikov via Digitalmars-d-learn

I have the following code example:

```d
struct A{}

A[5] a;
ulong[] idx = [1,3,4];

auto get()
{
return idx.map!(_ => a[_]);
}

foreach(i; 0 .. a.length)
write([i], " ");
writeln;

foreach(ref b; get())
write(, " ");
writeln;
```

How can I change `get` function so it returns the references to 
the content in `a`?


Is there a good documentation describing how to avoid copying of 
structs in the code?