www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array/list of objects of different type but with same interface

reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
Hello all,

I'm considering a rewrite of some old C/C++ simulation code in D.  This code is 
a "stock market" game where lots of different agents with different strategies 
compete and try to outdo one another at trading.

What I'm puzzling over is how to effectively store the collection of agents. 
These will be arbitrary in number (and agents might in principle be created or 
destroyed during the game), will all have the same interface, but will have 
different implementations -- some may use look-up tables, some may be
controlled 
by neural networks, etc. etc.

When I originally wrote this in C, I just used an array of pointers to agents. 
In C++ I did something similar, defining an agent class of which all 
implementations were subclasses.

I'm just wondering what might be the best and most idiomatic way to do this in 
D.  My likely agent design will be a "policy class" style,

     struct Agent(alias X, alias Y, ...)
     {
         mixin X;
         mixin Y;
         // etc...
     }

... with template mixins to implement the individual components that vary by 
agent type.  The public interface will be identical for all agents.

What I can't work out is how to store a collection of these agents in an array 
or similarly efficient container.  Can anyone advise?

Thanks and best wishes,

     -- Joe
Jun 20 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/20/2012 02:01 PM, Joseph Rushton Wakeling wrote:

 What I'm puzzling over is how to effectively store the collection of
 agents. These will be arbitrary in number (and agents might in principle
 be created or destroyed during the game), will all have the same
 interface, but will have different implementations -- some may use
 look-up tables, some may be controlled by neural networks, etc. etc.

 When I originally wrote this in C, I just used an array of pointers to
 agents. In C++ I did something similar, defining an agent class of which
 all implementations were subclasses.

 I'm just wondering what might be the best and most idiomatic way to do
 this in D. My likely agent design will be a "policy class" style,

 struct Agent(alias X, alias Y, ...)
 {
 mixin X;
 mixin Y;
 // etc...
 }

 ... with template mixins to implement the individual components that
 vary by agent type. The public interface will be identical for all 
agents.
 What I can't work out is how to store a collection of these agents in an
 array or similarly efficient container. Can anyone advise?
Sounds like you need an 'interface' and classes that implement it. The following code uses simple string mixins: import std.stdio; interface Agent { double trade(); } class SmartAgent : Agent { double trade() { writeln("Trading smartly"); return 42; } } class ConfigurableAgent(string X, string Y) : Agent { mixin(X); mixin(Y); double trade() { writefln("Trading with type '%s' and '%s'", typeid(x), typeid(y)); return x + y; } } void main() { Agent[] agents; agents ~= new SmartAgent(); agents ~= new ConfigurableAgent!("int x;", "int y;"); agents ~= new ConfigurableAgent!("double x;", "long y;"); foreach (agent; agents) { agent.trade(); } } Ali
Jun 20 2012
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 20/06/12 22:14, Ali Çehreli wrote:
 void main()
 {
     Agent[] agents;
     agents ~= new SmartAgent();
     agents ~= new ConfigurableAgent!("int x;", "int y;");
     agents ~= new ConfigurableAgent!("double x;", "long y;");

     foreach (agent; agents) {
         agent.trade();
     }
 }
Ahh, I hadn't realized that I could create an array whose "type" was the interface -- though it makes sense. Thanks very much! Is there any way to do this with structs instead of classes? I ask because in my experience the difference in performance is dramatic.
Jun 20 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Joseph Rushton Wakeling:

 Is there any way to do this with structs instead of classes?  I 
 ask because in my experience the difference in performance is 
 dramatic.
std.variant.Algebraic? Bye, bearophile
Jun 20 2012
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 20/06/12 23:00, bearophile wrote:
 std.variant.Algebraic?
Interesting thought. I fear it's a no-go as you'd have to specify up-front all the possible agent choices, but I'll have a play ... Thanks very much! :-)
Jun 21 2012