www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Creating an array of default-constructed class instances

reply "Simon" <none example.org> writes:
Hi, I'm new to the D programming language.  Overall I'm liking
things very much, but I'm still getting the hang of a few things.

Here's a basic programming pattern: I have a class called Thing,
and while I'm coding I decide I need N Thing instances.

In C++ that's a matter of

std::vector<Thing> things(N);

In python, I can use a list comprehension.

things = [Thing() for _ in range(N)]

However, the obvious D version doesn't work.

auto things = new Thing[N];

Because Thing.init is null, this produces an array of null
references.  Of course, I can write a for loop to fill in the
array after creation, but this feels very un-D-like.  Is there a
straightforward way to create a bunch of class instances?
Feb 09 2013
next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 10 February 2013 at 06:14:37 UTC, Simon wrote:
 Hi, I'm new to the D programming language.  Overall I'm liking
 things very much, but I'm still getting the hang of a few 
 things.

 Here's a basic programming pattern: I have a class called Thing,
 and while I'm coding I decide I need N Thing instances.

 In C++ that's a matter of

 std::vector<Thing> things(N);

 In python, I can use a list comprehension.

 things = [Thing() for _ in range(N)]

 However, the obvious D version doesn't work.

 auto things = new Thing[N];

 Because Thing.init is null, this produces an array of null
 references.  Of course, I can write a for loop to fill in the
 array after creation, but this feels very un-D-like.  Is there a
 straightforward way to create a bunch of class instances?
You can create separate function which fills array with instances and return it. You can make Thing a struct aliased to array of classes which again initializes properly in constructor an array. But then you should take care that struct constructor is called.
Feb 09 2013
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/09/2013 10:14 PM, Simon wrote:
 Hi, I'm new to the D programming language. Overall I'm liking
 things very much, but I'm still getting the hang of a few things.

 Here's a basic programming pattern: I have a class called Thing,
 and while I'm coding I decide I need N Thing instances.

 In C++ that's a matter of

 std::vector<Thing> things(N);

 In python, I can use a list comprehension.

 things = [Thing() for _ in range(N)]

 However, the obvious D version doesn't work.

 auto things = new Thing[N];

 Because Thing.init is null, this produces an array of null
 references. Of course, I can write a for loop to fill in the
 array after creation, but this feels very un-D-like. Is there a
 straightforward way to create a bunch of class instances?
Here is one way: import std.stdio; import std.range; import std.algorithm; class Thing { int i; this(int i) { this.i = i; } } void main() { auto things = iota(10).map!(i => new Thing(i))().array; } Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Feb 09 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/09/2013 10:52 PM, Ali Çehreli wrote:

   auto things = iota(10).map!(i => new Thing(i))().array;
Actually, without the extra parentheses: auto things = iota(10).map!(i => new Thing(i)).array; Ali
Feb 09 2013
parent reply "Simon" <none example.org> writes:
On Sunday, 10 February 2013 at 06:57:42 UTC, Ali Çehreli wrote:
 On 02/09/2013 10:52 PM, Ali Çehreli wrote:

   auto things = iota(10).map!(i => new Thing(i))().array;
Actually, without the extra parentheses: auto things = iota(10).map!(i => new Thing(i)).array; Ali
It's a shame there isn't any simple syntax for it, but that's some neat and flexible code. Thanks!
Feb 09 2013
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Feb 10, 2013 at 8:40 AM, Simon <none example.org> wrote:

     auto things = iota(10).map!(i => new Thing(i)).array;

 Ali
It's a shame there isn't any simple syntax for it, but that's some neat and flexible code.
Oh, you can easily use a template: import std.array; import std.algorithm; import std.conv; import std.range; import std.stdio; class Thing { int i; this(int i) { this.i = i; } void toString(scope void delegate(const(char)[]) sink) const { sink("Thing: " ~ to!string(i)); } } /// Helper template What[] makeArray(alias What)(size_t size) { return iota(size).map!(i => new What(i)).array; } void main() { auto things = makeArray!(Thing)(10); writeln(things); }
Feb 10 2013
prev sibling next sibling parent reply Jos van Uden <usenet fwend.com> writes:
On 10-2-2013 7:14, Simon wrote:
 Hi, I'm new to the D programming language.  Overall I'm liking
 things very much, but I'm still getting the hang of a few things.

 Here's a basic programming pattern: I have a class called Thing,
 and while I'm coding I decide I need N Thing instances.

 In C++ that's a matter of

 std::vector<Thing> things(N);

 In python, I can use a list comprehension.

 things = [Thing() for _ in range(N)]

 However, the obvious D version doesn't work.

 auto things = new Thing[N];

 Because Thing.init is null, this produces an array of null
 references.  Of course, I can write a for loop to fill in the
 array after creation, but this feels very un-D-like.  Is there a
 straightforward way to create a bunch of class instances?
import std.stdio, std.algorithm; class Thing { int i; this(int i) { this.i = i; } } void main() { auto things = new Thing[10]; fill(things, new Thing(5)); foreach (t; things) writef("%d ", t.i); }
Feb 10 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 10 February 2013 at 09:48:04 UTC, Jos van Uden wrote:
 On 10-2-2013 7:14, Simon wrote:
 Hi, I'm new to the D programming language.  Overall I'm liking
 things very much, but I'm still getting the hang of a few 
 things.

 Here's a basic programming pattern: I have a class called 
 Thing,
 and while I'm coding I decide I need N Thing instances.

 In C++ that's a matter of

 std::vector<Thing> things(N);

 In python, I can use a list comprehension.

 things = [Thing() for _ in range(N)]

 However, the obvious D version doesn't work.

 auto things = new Thing[N];

 Because Thing.init is null, this produces an array of null
 references.  Of course, I can write a for loop to fill in the
 array after creation, but this feels very un-D-like.  Is there 
 a
 straightforward way to create a bunch of class instances?
import std.stdio, std.algorithm; class Thing { int i; this(int i) { this.i = i; } } void main() { auto things = new Thing[10]; fill(things, new Thing(5)); foreach (t; things) writef("%d ", t.i); }
HELL NO!!!! What you did just right there is allocate a *single* thing _instance_ and then place 10 _references_ to that same thing in the array.
Feb 10 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/10/2013 03:18 AM, monarch_dodra wrote:
 On Sunday, 10 February 2013 at 09:48:04 UTC, Jos van Uden wrote:
 auto things = new Thing[10];
 fill(things, new Thing(5));
 What you did just right there is allocate a *single* thing _instance_
 and then place 10 _references_ to that same thing in the array.
And in case that is what we really wanted, there is the simpler but sometimes confusing array-wise syntax: auto things = new Thing[10]; things[] = new Thing(5); Ali
Feb 10 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 10 February 2013 at 06:14:37 UTC, Simon wrote:
 Hi, I'm new to the D programming language.  Overall I'm liking
 things very much, but I'm still getting the hang of a few 
 things.

 Here's a basic programming pattern: I have a class called Thing,
 and while I'm coding I decide I need N Thing instances.

 In C++ that's a matter of

 std::vector<Thing> things(N);

 In python, I can use a list comprehension.

 things = [Thing() for _ in range(N)]

 However, the obvious D version doesn't work.

 auto things = new Thing[N];

 Because Thing.init is null, this produces an array of null
 references.  Of course, I can write a for loop to fill in the
 array after creation, but this feels very un-D-like.  Is there a
 straightforward way to create a bunch of class instances?
The difference is that C++ will *place* the instances inside the vector. A *true* C++ equivalent would be to declare: std::vector<Thing*> things(N); As you can see, same problem. Honestly, there are a lot of fancy ways to go around the problem, but quite frankly,I think simple is best: //---- auto myThings = new Thing[](N); foreach(ref aThing; myThings) aThing = new Thing(); //----- It's not fancy, but it gets the job done. You won't confuse anyone with the code, and there is very little risk of subtle bugs (appart from forgetting the ref in the foreach loop.
Feb 10 2013