digitalmars.D.learn - How to return a reference to structs?
- Andrey Zherikov (20/20) Nov 04 2021 I have the following code example:
- Paul Backus (9/27) Nov 04 2021 Have the lambda return by reference:
- Andrey Zherikov (2/9) Nov 04 2021 That works, thanks!
- Andrey Zherikov (11/44) Nov 04 2021 Making this example a bit complex: I want `get` to return
- Paul Backus (11/31) Nov 04 2021 Since there are no such thing as `ref` variables in D, you can't
- kdevel (9/13) Nov 05 2021 [...]
- =?UTF-8?Q?Ali_=c3=87ehreli?= (22/31) Nov 05 2021 Indexes are typed as size_t, which is ulong for 64-bit and uint for
- Andrey Zherikov (2/7) Nov 05 2021 Ah, good point. Thanks!
- Andrey Zherikov (26/33) Nov 05 2021 Adding a bit of CTFE:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/29) Nov 05 2021 On 11/5/21 5:43 PM, Andrey Zherikov wrote:
- Andrey Zherikov (36/49) Nov 06 2021 `get()` will return nothing in this case. But I can make them non
- =?UTF-8?Q?Ali_=c3=87ehreli?= (19/27) Nov 06 2021 I think the error you got is a bug and should be reported because it
- Andrey Zherikov (7/12) Nov 06 2021 I have a [CLI-parsing
- =?UTF-8?Q?Ali_=c3=87ehreli?= (23/31) Nov 06 2021 'indexed' does not iterate the collection; just the ones that are in the...
- data pulverizer (5/5) Nov 06 2021 Hi,
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(&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?
Nov 04 2021
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(&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: ```d auto get() { return idx.map!(ref (i) => a[i]); } ```
Nov 04 2021
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!
Nov 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: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 } ```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(&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: ```d auto get() { return idx.map!(ref (i) => a[i]); } ```
Nov 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: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(&a[i], i)); } ```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 } ```
Nov 04 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>
Nov 05 2021
On 11/5/21 11:44 AM, kdevel wrote:On Thursday, 4 November 2021 at 11:26:30 UTC, Andrey Zherikov 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: 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; } AliI 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)?
Nov 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]; // <-- HereAh, good point. Thanks!
Nov 05 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:Adding a bit of CTFE: ```d 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?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]; // <-- HereAh, good point. Thanks!
Nov 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
Nov 05 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;`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) => &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.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.
Nov 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
Nov 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#indexedI 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/sou ce/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.
Nov 06 2021
On 11/6/21 8:57 AM, Andrey Zherikov wrote:On Saturday, 6 November 2021 at 13:57:47 UTC, Ali =C3=87ehreli wrote:eHave you considered std.range.indexed, which should at least cover th='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=20 array, 'indexed' will touch just two elements.case of accessing: https://dlang.org/phobos/std_range.html#indexedI don't need to iterate over whole collection, but subset of it.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=20 mutate the elements: import std.algorithm; import std.range; import std.stdio; void main() { int[] numbers =3D [ 0, 1, 2, 3, 4, 5 ]; size_t[] specials =3D [ 1, 5 ]; size_t[] moreSpecials =3D [ 2, 3, 4 ]; numbers.indexed(specials).each!((ref n) =3D> n *=3D 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
Nov 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.
Nov 06 2021