Jump to page: 1 2
Thread overview
How to return a reference to structs?
Nov 04, 2021
Andrey Zherikov
Nov 04, 2021
Paul Backus
Nov 04, 2021
Andrey Zherikov
Nov 04, 2021
Andrey Zherikov
Nov 04, 2021
Paul Backus
Nov 05, 2021
kdevel
Nov 05, 2021
Ali Çehreli
Nov 05, 2021
Andrey Zherikov
Nov 06, 2021
Andrey Zherikov
Nov 06, 2021
Ali Çehreli
Nov 06, 2021
Andrey Zherikov
Nov 06, 2021
Ali Çehreli
Nov 06, 2021
Andrey Zherikov
Nov 07, 2021
Ali Çehreli
Nov 06, 2021
data pulverizer
November 04, 2021

I have the following code example:

struct A{}

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

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

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

foreach(ref b; get())
    write(&b, " ");
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?

November 04, 2021

On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov wrote:

>

I have the following code example:

struct A{}

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

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

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

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

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

Have the lambda return by reference:

auto get()
{
    return idx.map!(ref (i) => a[i]);
}
November 04, 2021

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

>

Have the lambda return by reference:

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

That works, thanks!

November 04, 2021

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:

struct A{}

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

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

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

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

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

Have the lambda return by reference:

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?

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

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:

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?

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:

auto get()
{
    return idx.map!((i) => tuple(&a[i], i));
}
November 05, 2021

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] https://stackoverflow.com/questions/3174850/what-is-the-correct-type-for-array-indexes-in-c

November 05, 2021
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(&a[i], " ");
  writeln;

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

Ali

November 05, 2021

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!

November 06, 2021

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:

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

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

November 05, 2021
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) => &ar[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

« First   ‹ Prev
1 2