www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Assigning to array of structs with custom constructor

reply cc <cc nevernet.com> writes:
```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
next sibling parent reply Alain De Vos <devosalain ymail.com> writes:
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
parent cc <cc nevernet.com> writes:
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
prev sibling next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
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
parent cc <cc nevernet.com> writes:
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
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
parent cc <cc nevernet.com> writes:
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
prev sibling parent reply rassoc <rassoc posteo.de> writes:
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
next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
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
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 26 April 2022 at 00:57:54 UTC, Ali Çehreli wrote:
 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?
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 79
Apr 25 2022
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
prev sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
😀

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
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 4/25/22 21:32, Salih Dincer wrote:

 So the problem is that the structure is not in the inter-module space
Nested 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