digitalmars.D.learn - Assigning to array of structs with custom constructor
- cc (13/13) Apr 25 2022 ```d
- Alain De Vos (12/12) Apr 25 2022 Not really an answer but this works,
- cc (4/12) Apr 25 2022 Right, I can append individual elements, but can't assign or
- Stanislav Blinov (5/18) Apr 25 2022 Make it explicit:
- cc (12/16) Apr 25 2022 There's that too, but I still have to iterate manually. e.g.:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (13/21) Apr 25 2022 I don't understand why that syntax exists. I always write it like this:
- cc (3/5) Apr 25 2022 Ahh that'll do it alright, thanks
- rassoc (10/23) Apr 25 2022 This works:
- Salih Dincer (46/54) Apr 25 2022 Thank you...
- =?UTF-8?Q?Ali_=c3=87ehreli?= (38/44) Apr 25 2022 There must be something wrong. map is commonly used with chunks(),
- Salih Dincer (52/60) Apr 25 2022 Of course, I have a few friends here:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (64/65) Apr 25 2022 Hm. I can't reproduce any of that. I did two things:
- Salih Dincer (8/19) Apr 25 2022 😀
- =?UTF-8?Q?Ali_=c3=87ehreli?= (9/12) Apr 25 2022 Nested structs carry an additional pointer to their containing context.
```d struct Foo { string s; this(string s) { this.s = s; } } Foo foo = "a"; Foo[] foos = ["a"]; // Error: cannot implicitly convert expression `["a"]` of type `string[]` to `Foo[]` Foo[] foos = cast(Foo[]) ["a"]; // Error: e2ir: cannot cast `"a"` of type `string` to type `Foo` ``` Was there a way to do this? I thought I recalled seeing something like this before, but I can't seem to find it.
Apr 25 2022
Not really an answer but this works, ``` struct Foo { string s; this(string s) { this.s = s; } } void main(){ Foo foo = "a"; Foo[] foos; foos ~=foo; }% ```
Apr 25 2022
On Monday, 25 April 2022 at 15:00:13 UTC, Alain De Vos wrote:Not really an answer but this works, ``` void main(){ Foo foo = "a"; Foo[] foos; foos ~=foo; }% ```Right, I can append individual elements, but can't assign or append a slice of a type that can be individually cast to the struct.
Apr 25 2022
On Monday, 25 April 2022 at 14:36:25 UTC, cc wrote:```d struct Foo { string s; this(string s) { this.s = s; } } Foo foo = "a"; Foo[] foos = ["a"]; // Error: cannot implicitly convert expression `["a"]` of type `string[]` to `Foo[]` Foo[] foos = cast(Foo[]) ["a"]; // Error: e2ir: cannot cast `"a"` of type `string` to type `Foo` ``` Was there a way to do this? I thought I recalled seeing something like this before, but I can't seem to find it.Make it explicit: ```d Foo[] foos = [Foo("a")]; ```
Apr 25 2022
On Monday, 25 April 2022 at 15:13:51 UTC, Stanislav Blinov wrote:Make it explicit: ```d Foo[] foos = [Foo("a")]; ```There's that too, but I still have to iterate manually. e.g.: ```d string[] ss = loadABunchOfStringsFromSomewhere(); //Foo[] foos = ss; //error Foo[] foos; foos.reserve(ss.length); foreach (s; ss) foos ~= Foo(s); ``` Was just hoping there was a way to streamline it within the struct definition.
Apr 25 2022
On 4/25/22 07:36, cc wrote:```d struct Foo { string s; this(string s) { this.s = s; } } Foo foo = "a";I don't understand why that syntax exists. I always write it like this: auto foo = Foo("a");Foo[] foos = ["a"]; // Error: cannot implicitly convert expression `["a"]` of type `string[]` to `Foo[]`This is a way: Foo[] foos = [Foo("a")]; Or: import std.stdio; import std.algorithm; import std.range; import std.conv; auto arr = iota(10).map!(i => Foo(i.text)).array; writeln(arr); Ali
Apr 25 2022
On Monday, 25 April 2022 at 15:23:12 UTC, Ali Çehreli wrote:auto arr = iota(10).map!(i => Foo(i.text)).array;On Monday, 25 April 2022 at 16:11:47 UTC, rassoc wrote:Foo[] arr = ["abc", "def", "ghi"].map!Foo.array;Ahh that'll do it alright, thanks
Apr 25 2022
On 4/25/22 16:36, cc via Digitalmars-d-learn wrote:```d struct Foo {     string s;     this(string s) { this.s = s; } } Foo foo = "a"; Foo[] foos = ["a"]; // Error: cannot implicitly convert expression `["a"]` of type `string[]` to `Foo[]` Foo[] foos = cast(Foo[]) ["a"]; // Error: e2ir: cannot cast `"a"` of type `string` to type `Foo` ``` Was there a way to do this? I thought I recalled seeing something like this before, but I can't seem to find it.This works: ```d import std; void main() { struct Foo { string s; } Foo[] arr = ["abc", "def", "ghi"].map!Foo.array; arr.writeln; // => [Foo("abc"), Foo("def"), Foo("ghi")] } ```
Apr 25 2022
On Monday, 25 April 2022 at 16:11:47 UTC, rassoc wrote:```d import std; void main() { struct Foo { string s; } Foo[] arr = ["abc", "def", "ghi"].map!Foo.array; arr.writeln; // => [Foo("abc"), Foo("def"), Foo("ghi")] } ```Thank you... Very very nice and simple but not extensible! Because it cannot be used with other possibilities such as ```chunks()``` and ```take()```. Also it cannot be customized with ```toString()```. I guess even when ```this()``` constructor is added, ```map()``` explodes! So it not to explode, it is necessary to move away from simplicity: ```d import std.algorithm; import std.range, std.stdio; void main() { struct Foo { string s; /* string s; string toString() { return s; }//*/ } auto arr1 = ["abc", "def", "ghi"] .map!Foo.array; /* .map!(a => Foo(a)) .array;//*/ typeof(arr1).stringof.writeln(": ", arr1); struct Bar { string s; //* this(R)(R result) { import std.conv : to; this.s = result.to!string; }//*/ string toString() { return s; } } auto arr2 = "abcdefghi" .chunks(3) .map!(a => Bar(a)) .array; typeof(arr2).stringof.writeln(": ", arr2); } /* OUTPUT: Foo[]: [Foo("abc"), Foo("def"), Foo("ghi")] Bar[]: [abc, def, ghi] */ ``` SDB 79
Apr 25 2022
On 4/25/22 16:59, Salih Dincer wrote:Because it cannot be used with other possibilities such as ```chunks()``` and ```take()```.There must be something wrong. map is commonly used with chunks(), take(), etc.Also it cannot be customized with ```toString()```.Can you show examples of these please?I guess even when ```this()``` constructor is added, ```map()``` explodes!Ah! Now I tried *removing* Bar.this and the compilation failed. Perhaps you left the working code in? (?) For others: 1) Remove Bar.this 2) The code will fail below: auto arr2 = "abcdefghi" .chunks(3) .map!(a => Bar(a)) <-- ERROR .array; Error: cannot implicitly convert expression `a` of type `Take!string` to `string` One confusing thing is the fact that we learn that chunks uses take in its implementation. I think it's cool but a newcomer may be confused with where that Take comes from. Let's put that aside. Then the compilation error is easy to understdand because chunks returns a range itself but it is not possible to make a Bar from a range. I don't agree that this is a problem with map's usability. The type system doesn't know what to do. Here is one way of fixing the issue, not surprisingly, with map itself. ;) import std.conv : to; auto arr2 = "abcdefghi" .chunks(3) .map!(c => c.to!string) // <-- ADDED .map!(a => Bar(a)) .array; Or, one can use a single map expression: auto arr2 = "abcdefghi" .chunks(3) .map!(a => Bar(a.to!string)) // <-- COMBINED .array; Or, a function can be called, etc. But to remove a misunderstanding, map can be used with most other range algorithms, in the standard library, provided by the programmer, etc. Ali
Apr 25 2022
On Tuesday, 26 April 2022 at 00:57:54 UTC, Ali Çehreli wrote:On 4/25/22 16:59, Salih Dincer wrote:Of course, I have a few friends here: and a lot of errors 😀 ```d struct Bar { string s; this(R)(R result) { import std.conv : to; this.s = result.to!string; } string toString() { return s; } } auto parts = "abcdefghi".chunks(3); auto compiled = parts.map!(a => Bar(a)); auto notCompile1 = parts.map!Bar; /* Error 1: instantiated from here: `map!(Chunks!string)`*/ auto notCompile2 = parts.map!(c => c.to!string) .map!Bar; /* Error 1: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(604) : cannot access frame pointer of `source.main.Bar` Error 2: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(499) : template instance `std.algorithm.iteration.MapResult!(Bar, MapResult!(__lambda4, Chunks!string))` error instantiating Error 3: instantiated from here: `map!(MapResult!(__lambda4, Chunks!string))` */ auto notCompile3 = parts.array.map!Bar; /* Error 1: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(604) : cannot access frame pointer of `source.main.Bar` Error 2: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(616) : cannot access frame pointer of `source.main.Bar` Error 3: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(499) : template instance `std.algorithm.iteration.MapResult!(Bar, Take!string[])` error instantiating Error 4: instantiated from here: `map!(Take!string */ auto arr = compiled.array; /* [abc, def, ghi] auto arr2 = str.chunks(3) .map!(a => Bar(a)) .array;//*/ arr.writeln(": ", typeof(arr).stringof); ``` SDB 79Because it cannot be used with other possibilities such as ```chunks()``` and ```take()```.There must be something wrong. map is commonly used with chunks(), take(), etc.Also it cannot be customized with ```toString()```.Can you show examples of these please?
Apr 25 2022
On 4/25/22 19:37, Salih Dincer wrote:a lot of errors 😀Hm. I can't reproduce any of that. I did two things: 1) Added necessary import directives 2) Moved all expressions into the main() function I did not change anything else. The program below compiles and works with all these compilers: - dmd 2.098.1 - dmd 2.099.1 - gdc 11.2.0 - ldc 1.28.1 (based on DMD v2.098.1 and LLVM 13.0.1) Are you using a very old compiler? import std.range; import std.algorithm; import std.conv; import std.stdio; struct Bar { string s; this(R)(R result) { import std.conv : to; this.s = result.to!string; } string toString() { return s; } } void main() { auto parts = "abcdefghi".chunks(3); auto compiled = parts.map!(a => Bar(a)); // NOTE: PLEASE IGNORE THE ERROR MESSAGES BELOW. // EVERYTHING COMPILES AND WORKS. auto notCompile1 = parts.map!Bar; /* Error 1: instantiated from here: `map!(Chunks!string)`*/ auto notCompile2 = parts.map!(c => c.to!string) .map!Bar; /* Error 1: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(604) : cannot access frame pointer of `source.main.Bar` Error 2: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(499) : template instance `std.algorithm.iteration.MapResult!(Bar, MapResult!(__lambda4, Chunks!string))` error instantiating Error 3: instantiated from here: `map!(MapResult!(__lambda4, Chunks!string))` */ auto notCompile3 = parts.array.map!Bar; /* Error 1: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(604) : cannot access frame pointer of `source.main.Bar` Error 2: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(616) : cannot access frame pointer of `source.main.Bar` Error 3: /usr/src/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(499) : template instance `std.algorithm.iteration.MapResult!(Bar, Take!string[])` error instantiating Error 4: instantiated from here: `map!(Take!string */ auto arr = compiled.array; /* [abc, def, ghi] auto arr2 = str.chunks(3) .map!(a => Bar(a)) .array;//*/ arr.writeln(": ", typeof(arr).stringof); } Ali
Apr 25 2022
😀 So the problem is that the structure is not in the inter-module space On Monday, 25 April 2022 at 16:11:47 UTC, rassoc wrote:This works: ```d import std; void main() { struct Foo { string s; } Foo[] arr = ["abc", "def", "ghi"].map!Foo.array; arr.writeln; // => [Foo("abc"), Foo("def"), Foo("ghi")] } ```If ```sruct Foo {}``` is not taken outside of ```main()``` it will fail for many possibilities! **For example:**Error: cannot access frame pointer of `source.main.Foo`SDB 79
Apr 25 2022
On 4/25/22 21:32, Salih Dincer wrote:So the problem is that the structure is not in the inter-module spaceNested structs carry an additional pointer to their containing context. When they don't need the context, we define them with 'static': void foo() { static struct Bar { } }If ```sruct Foo {}``` is not taken outside of ```main()``` it will fail for many possibilities!Only if the struct needs the context. Otherwise, nested structs should be defined with 'static' and there is no issue with map... Ali
Apr 25 2022