comp.lang.ada
 help / color / mirror / Atom feed
* Runtime type selection
@ 2009-10-11 16:41 xorque
  2009-10-11 17:02 ` Niklas Holsti
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: xorque @ 2009-10-11 16:41 UTC (permalink / raw)


Hello.

I'd like to develop a program that processes a graph. The contents of
the graph are a random selection of objects of different types (all
elements may be of the same type or may all be different - assuming
there are enough types defined). By 'type' in this case, I am
referring
to Ada types.

The basic problem is that I want to create an object of a type picked
at
random, at runtime. I'm not entirely sure what my options are here.

I could create a base tagged type and derive a set of types from that
base, selecting at random. I could use variant records. It seems that
in
either case, I'd need to create an enumeration type with a 1:1 mapping
between enumeration values and derived types.

Both of these solutions seem a little unwieldly. They also seem like
they'd end up making the program difficult to extend (I'd ideally just
like to derive a new type and have it automatically available to be
selected at random for the graph).

Any ideas would be appreciated. I appreciate the problem is a little
abstract...



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 16:41 Runtime type selection xorque
@ 2009-10-11 17:02 ` Niklas Holsti
  2009-10-11 17:15   ` xorque
  2009-10-11 17:15 ` mockturtle
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Niklas Holsti @ 2009-10-11 17:02 UTC (permalink / raw)


xorque wrote:
> Hello.
> 
> I'd like to develop a program that processes a graph. The contents of
> the graph are a random selection of objects of different types (all
> elements may be of the same type or may all be different - assuming
> there are enough types defined). By 'type' in this case, I am
> referring
> to Ada types.
> 
> The basic problem is that I want to create an object of a type picked
> at
> random, at runtime. I'm not entirely sure what my options are here.
> 
> I could create a base tagged type and derive a set of types from that
> base, selecting at random. I could use variant records. It seems that
> in
> either case, I'd need to create an enumeration type with a 1:1 mapping
> between enumeration values and derived types.
> 
> Both of these solutions seem a little unwieldly. They also seem like
> they'd end up making the program difficult to extend (I'd ideally just
> like to derive a new type and have it automatically available to be
> selected at random for the graph).

Keep a list or array of (accesses to) a factory function for each 
possible (derived) type. When you derive a new type from the base 
graph-element type, add its factory function to this list (this is often 
called "registering" the new type/function). When you want to make a 
graph element of a "random" type, pick a random index into the list or 
array of factory functions and call the chosen function, which creates 
the new element and returns an access to it (type access all 
Base_Graph_Element_Type'Class).

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 16:41 Runtime type selection xorque
  2009-10-11 17:02 ` Niklas Holsti
@ 2009-10-11 17:15 ` mockturtle
  2009-10-11 20:06 ` Dmitry A. Kazakov
  2009-10-13 15:11 ` xorque
  3 siblings, 0 replies; 17+ messages in thread
From: mockturtle @ 2009-10-11 17:15 UTC (permalink / raw)


On Oct 11, 6:41 pm, xorque <xorquew...@googlemail.com> wrote:
> Hello.
>
> I'd like to develop a program that processes a graph. The contents of
> the graph are a random selection of objects of different types (all
> elements may be of the same type or may all be different - assuming
> there are enough types defined). By 'type' in this case, I am
> referring
> to Ada types.
>
> The basic problem is that I want to create an object of a type picked
> at
> random, at runtime. I'm not entirely sure what my options are here.
>
> I could create a base tagged type and derive a set of types from that
> base, selecting at random. I could use variant records. It seems that
> in
> either case, I'd need to create an enumeration type with a 1:1 mapping
> between enumeration values and derived types.
>
> Both of these solutions seem a little unwieldly. They also seem like
> they'd end up making the program difficult to extend (I'd ideally just
> like to derive a new type and have it automatically available to be
> selected at random for the graph).
>
> Any ideas would be appreciated. I appreciate the problem is a little
> abstract...

I am making this  suggestion as I write, so maybe it could prove
unfeasible, but maybe it will inspire you.

I would create a base tagged type, so that all your types are
descendent of a common ancestor.  Then I would define a "constructor
callback", that is a type that represents an access to a function that
return a class-wide access type to a newly created object. Finally, I
would create a container (a vector?) of constructor callbacks.   More
or less, something like this

   type Root is tagged null record;

   type Root_Class_Access is access Root'Class;

   type Callback is access function return Root_Class_Access;

   package Callback_Vectors is
       new Containers.Vectors(Natural, Callback);

   Callback_Table : Callback_Vectors.Vector;

[Please note: I did not check the code above with an actual Ada
compiler, so maybe it is full of errors (beside the missing "with"),
but I hope it clarifies what I mean]

 When I want to add a new type to my system, I simply "register" the
constructor of the new type by inserting it into Callback_Table.  When
I want to generate an object at random I simply choose one callback
from the container and call it.

As I said, I made this in "real time" while writing, so I hope this
makes some sense... ;-)

Cheers



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 17:02 ` Niklas Holsti
@ 2009-10-11 17:15   ` xorque
  2009-10-11 19:54     ` Niklas Holsti
  0 siblings, 1 reply; 17+ messages in thread
From: xorque @ 2009-10-11 17:15 UTC (permalink / raw)


On Oct 11, 5:02 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
wrote:
> Keep a list or array of (accesses to) a factory function for each
> possible (derived) type.

'Lo,

That does sound like the sort of thing I'd have done in C. I still
have a nagging sensation that Ada actually provides other means to
do this based on such things as the 'Tag attribute.

I'll keep this suggestion in mind in the meantime, though.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 17:15   ` xorque
@ 2009-10-11 19:54     ` Niklas Holsti
  2009-10-12  9:26       ` Georg Bauhaus
                         ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Niklas Holsti @ 2009-10-11 19:54 UTC (permalink / raw)


xorque wrote:
> On Oct 11, 5:02 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
> wrote:
>> Keep a list or array of (accesses to) a factory function for each
>> possible (derived) type.
> 
> 'Lo,
> 
> That does sound like the sort of thing I'd have done in C.

Yes. Ada makes it easier since you can use elaboration-time statement 
blocks in package bodies to register stuff.

> I still
> have a nagging sensation that Ada actually provides other means to
> do this based on such things as the 'Tag attribute.

Did you read about the package Ada.Tags (RM 3.9)? There is a generic 
function Ada.Tags.Generic_Dispatching_Constructor that takes a tag as 
parameter and creates an object with that tag, but I don't hink there is 
any way to find the tags for all types in a given derivation class. So 
even with  Ada.Tags.Generic_Dispatching_Constructor your program still 
has to register the types, or their tags, or a prototype object of each 
type, to create the program-accessible set of types/tags that can be in 
the graph.

Perhaps some expert can explain why this reflection capability (find 
tags for all derived types in a class) was not included in Ada.Tags? 
Perhaps because Ada run-time systems do not need such a function for 
their own purposes?

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 16:41 Runtime type selection xorque
  2009-10-11 17:02 ` Niklas Holsti
  2009-10-11 17:15 ` mockturtle
@ 2009-10-11 20:06 ` Dmitry A. Kazakov
  2009-10-13 10:45   ` Colin Paul Gloster
  2009-10-13 15:11 ` xorque
  3 siblings, 1 reply; 17+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-11 20:06 UTC (permalink / raw)


On Sun, 11 Oct 2009 09:41:54 -0700 (PDT), xorque wrote:

> I'd like to develop a program that processes a graph. The contents of
> the graph are a random selection of objects of different types (all
> elements may be of the same type or may all be different - assuming
> there are enough types defined). By 'type' in this case, I am
> referring to Ada types.
> 
> The basic problem is that I want to create an object of a type picked
> at random, at runtime. I'm not entirely sure what my options are here.

The problem is that graph nodes have nothing in common. Thus there is 
nothing except for the graph traversal operations you could implement on 
the graph as a whole.

> I could create a base tagged type and derive a set of types from that
> base, selecting at random. I could use variant records. It seems that
> in either case, I'd need to create an enumeration type with a 1:1 mapping
> between enumeration values and derived types.
> 
> Both of these solutions seem a little unwieldly. They also seem like
> they'd end up making the program difficult to extend (I'd ideally just
> like to derive a new type and have it automatically available to be
> selected at random for the graph).
> 
> Any ideas would be appreciated. I appreciate the problem is a little
> abstract...

In Ada there is a way to create linked structures (in particular graphs) of 
absolutely any elements of any type.

The idea goes as follows. You create a custom storage pool which holds the 
structure of links transparently to the objects allocated in it. For 
example, when you allocate something in the pool that is considered the 
contents of a node. The pointers to its neighbours in the graph are 
allocated in the same pool in front of the object itself. The operation new 
returns the pointer to the contents. So it is really anything that can 
become a node, even a task. (There are some difficulties when nodes are 
unconstrained arrays, but that works as well.)

Simple components uses this approach to implement doubly-linked lists:

http://www.dmitry-kazakov.de/ada/components.htm#Generic_Doubly_Linked_Web

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 19:54     ` Niklas Holsti
@ 2009-10-12  9:26       ` Georg Bauhaus
  2009-10-12 12:02         ` xorque
  2009-10-12 23:42       ` Randy Brukardt
  2009-10-13  0:59       ` Adam Beneschan
  2 siblings, 1 reply; 17+ messages in thread
From: Georg Bauhaus @ 2009-10-12  9:26 UTC (permalink / raw)


Niklas Holsti schrieb:

> Did you read about the package Ada.Tags (RM 3.9)?

Also, http://www.adaic.org/standards/05rat/html/Rat-2-6.html

> Perhaps some expert can explain why this reflection capability (find
> tags for all derived types in a class) was not included in Ada.Tags?
> Perhaps because Ada run-time systems do not need such a function for
> their own purposes?

Not an expert, but finding the tagged types after the fact
and when using GNAT can be done, sort of, with gnatxref -d .

Or, if the names of the types share a common substring,
using gnatfind.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-12  9:26       ` Georg Bauhaus
@ 2009-10-12 12:02         ` xorque
  0 siblings, 0 replies; 17+ messages in thread
From: xorque @ 2009-10-12 12:02 UTC (permalink / raw)


Thanks, all.

I'll be using Generic_Dispatching_Constructor with an array of
Ada.Tags.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 19:54     ` Niklas Holsti
  2009-10-12  9:26       ` Georg Bauhaus
@ 2009-10-12 23:42       ` Randy Brukardt
  2009-10-13  6:50         ` Niklas Holsti
  2009-10-13  0:59       ` Adam Beneschan
  2 siblings, 1 reply; 17+ messages in thread
From: Randy Brukardt @ 2009-10-12 23:42 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:4ad23819$0$6256$4f793bc4@news.tdc.fi...
...
> Did you read about the package Ada.Tags (RM 3.9)? There is a generic 
> function Ada.Tags.Generic_Dispatching_Constructor that takes a tag as 
> parameter and creates an object with that tag, but I don't hink there is 
> any way to find the tags for all types in a given derivation class. So 
> even with  Ada.Tags.Generic_Dispatching_Constructor your program still has 
> to register the types, or their tags, or a prototype object of each type, 
> to create the program-accessible set of types/tags that can be in the 
> graph.
>
> Perhaps some expert can explain why this reflection capability (find tags 
> for all derived types in a class) was not included in Ada.Tags? Perhaps 
> because Ada run-time systems do not need such a function for their own 
> purposes?

I think that would be impossible in general, for the same reason that the 
rules about what tags are returned from calls to Internal_Tag are mostly 
written with "may". The problem is that tagged types can be created and 
cease to exist asychronously with respect to a call to a function in 
Ada.Tags. (For instance, if another task creates a tagged type by calling a 
subprogram with such a type declaration.) The model of Ada.Tags is that is 
can be implemented either with a mostly static data structure (created at 
link-time) or with a fully dynamic structure. In the latter case, complex 
locking would be required to ensure any particular (useful) answer for one 
of these functions. In the former case, something similar to the dynamic 
structure (and locking) would be required to avoid returning non-existent 
tags. It was felt that such requirements would add a lot of complication and 
runtime cost to the implementation of this package without a corresponding 
benefit.

Finally, to actually implement some way to determine all of the tags of a 
particular class would require either a brute force search of all tags (very 
slow) or some complex additional data structures. (Remember that *every* 
tagged type and subtype has a corresponding 'Class, so this structure could 
get very large if you are using software that defines a lot of tagged types 
as Claw does.) The only language requirement is that each tagged type is 
connected to its immediate parent (in order to check type conversions), 
anything else further would be needed only to implement your proposed 
function. Even a list of all tags is not required to implement the language 
(although you may have a way to get it depending on your Ada.Tags 
implementation).

                                                 Randy.





^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 19:54     ` Niklas Holsti
  2009-10-12  9:26       ` Georg Bauhaus
  2009-10-12 23:42       ` Randy Brukardt
@ 2009-10-13  0:59       ` Adam Beneschan
  2009-10-13  7:01         ` Niklas Holsti
  2 siblings, 1 reply; 17+ messages in thread
From: Adam Beneschan @ 2009-10-13  0:59 UTC (permalink / raw)


On Oct 11, 12:54 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
wrote:
> xorque wrote:
> > On Oct 11, 5:02 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
> > wrote:
> >> Keep a list or array of (accesses to) a factory function for each
> >> possible (derived) type.
>
> > 'Lo,
>
> > That does sound like the sort of thing I'd have done in C.
>
> Yes. Ada makes it easier since you can use elaboration-time statement
> blocks in package bodies to register stuff.
>
> > I still
> > have a nagging sensation that Ada actually provides other means to
> > do this based on such things as the 'Tag attribute.
>
> Did you read about the package Ada.Tags (RM 3.9)? There is a generic
> function Ada.Tags.Generic_Dispatching_Constructor that takes a tag as
> parameter and creates an object with that tag, but I don't hink there is
> any way to find the tags for all types in a given derivation class. So
> even with  Ada.Tags.Generic_Dispatching_Constructor your program still
> has to register the types, or their tags, or a prototype object of each
> type, to create the program-accessible set of types/tags that can be in
> the graph.
>
> Perhaps some expert can explain why this reflection capability (find
> tags for all derived types in a class) was not included in Ada.Tags?
> Perhaps because Ada run-time systems do not need such a function for
> their own purposes?

Maybe I don't understand the problem clearly enough, but would
Ada.Tags.Descendant_Tag help?  This takes an external tag (a string)
and the 'Tag of the ancestor type, and will find a type in the
ancestor type's class whose 'External_Tag is the given external tag
string (as long as it's not more deeply nested than the ancestor
type).

                                     -- Adam



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-12 23:42       ` Randy Brukardt
@ 2009-10-13  6:50         ` Niklas Holsti
  0 siblings, 0 replies; 17+ messages in thread
From: Niklas Holsti @ 2009-10-13  6:50 UTC (permalink / raw)


Randy Brukardt wrote:
> "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
> news:4ad23819$0$6256$4f793bc4@news.tdc.fi...
> ...
>> Did you read about the package Ada.Tags (RM 3.9)? There is a generic 
>> function Ada.Tags.Generic_Dispatching_Constructor that takes a tag as 
>> parameter and creates an object with that tag, but I don't hink there is 
>> any way to find the tags for all types in a given derivation class. So 
>> even with  Ada.Tags.Generic_Dispatching_Constructor your program still has 
>> to register the types, or their tags, or a prototype object of each type, 
>> to create the program-accessible set of types/tags that can be in the 
>> graph.
>>
>> Perhaps some expert can explain why this reflection capability (find tags 
>> for all derived types in a class) was not included in Ada.Tags? Perhaps 
>> because Ada run-time systems do not need such a function for their own 
>> purposes?
> 
> I think that would be impossible in general, for the same reason that the 
> rules about what tags are returned from calls to Internal_Tag are mostly 
> written with "may". The problem is that tagged types can be created and 
> cease to exist asychronously with respect to a call to a function in 
> Ada.Tags. (For instance, if another task creates a tagged type by calling a 
> subprogram with such a type declaration.) The model of Ada.Tags is that is 
> can be implemented either with a mostly static data structure (created at 
> link-time) or with a fully dynamic structure. In the latter case, complex 
> locking would be required to ensure any particular (useful) answer for one 
> of these functions. In the former case, something similar to the dynamic 
> structure (and locking) would be required to avoid returning non-existent 
> tags. It was felt that such requirements would add a lot of complication and 
> runtime cost to the implementation of this package without a corresponding 
> benefit.

Thanks for this clear explanation, Randy. Interesting to hear that this 
question was actually discussed by the language definition team.

> The only language requirement is that each tagged type is 
> connected to its immediate parent (in order to check type conversions), 
> anything else further would be needed only to implement your proposed 
> function.

Well, I did not really mean to "propose" such a function, I only tried 
to explain to the OP (who could have made use of this functionality) 
that it is not provided now, but I could not myself explain why not, as 
you could.

As I understand it, Ada is not designed to support much reflection, so 
the absence of this function does not surprise or disappoint me. I don't 
know about the OP, of course...

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-13  0:59       ` Adam Beneschan
@ 2009-10-13  7:01         ` Niklas Holsti
  0 siblings, 0 replies; 17+ messages in thread
From: Niklas Holsti @ 2009-10-13  7:01 UTC (permalink / raw)


Adam Beneschan wrote:
> On Oct 11, 12:54 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
> wrote:
>> xorque wrote:
>>> On Oct 11, 5:02 pm, Niklas Holsti <niklas.hol...@tidorum.invalid>
>>> wrote:
>>>> Keep a list or array of (accesses to) a factory function for each
>>>> possible (derived) type.
>>> 'Lo,
>>> That does sound like the sort of thing I'd have done in C.
>> Yes. Ada makes it easier since you can use elaboration-time statement
>> blocks in package bodies to register stuff.
>>
>>> I still
>>> have a nagging sensation that Ada actually provides other means to
>>> do this based on such things as the 'Tag attribute.
>> Did you read about the package Ada.Tags (RM 3.9)? There is a generic
>> function Ada.Tags.Generic_Dispatching_Constructor that takes a tag as
>> parameter and creates an object with that tag, but I don't hink there is
>> any way to find the tags for all types in a given derivation class. So
>> even with  Ada.Tags.Generic_Dispatching_Constructor your program still
>> has to register the types, or their tags, or a prototype object of each
>> type, to create the program-accessible set of types/tags that can be in
>> the graph.
>>
>> Perhaps some expert can explain why this reflection capability (find
>> tags for all derived types in a class) was not included in Ada.Tags?
>> Perhaps because Ada run-time systems do not need such a function for
>> their own purposes?
> 
> Maybe I don't understand the problem clearly enough, but would
> Ada.Tags.Descendant_Tag help?  This takes an external tag (a string)
> and the 'Tag of the ancestor type, and will find a type in the
> ancestor type's class whose 'External_Tag is the given external tag
> string (as long as it's not more deeply nested than the ancestor
> type).

The program would still need to get the set of valid external tag 
strings from somewhere -- it could not just try one random string after 
another, blindly. As I understand the OP's problem, the program contains 
a base tagged type from which several types are derived, and the OP 
wants a method to create an object of some, randomly chosen, derived 
type. Ada.Tags.Descendant_Tag could be used only if the program 
registers the external tags for all such derived types in some central 
data structure. The OP intends to register the tags of the derived 
types, which is simpler.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-13 10:45   ` Colin Paul Gloster
@ 2009-10-13 10:17     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-13 10:17 UTC (permalink / raw)


On Tue, 13 Oct 2009 10:45:41 +0000, Colin Paul Gloster wrote:

> On Sun, 11 Oct 2009, Dmitry A. Kazakov wrote:
> 
>|----------------------------------------------------------------------------|
>|"                                                                           |
>|On Sun, 11 Oct 2009 09:41:54 -0700 (PDT), xorque wrote:                     |
>|                                                                            |
>|> I'd like to develop a program that processes a graph. The contents of     |
>|> the graph are a random selection of objects of different types (all       |
>|> elements may be of the same type or may all be different - assuming       |
>|> there are enough types defined). By 'type' in this case, I am             |
>|> referring to Ada types.                                                   |
>|>                                                                           |
>|> The basic problem is that I want to create an object of a type picked     |
>|> at random, at runtime. I'm not entirely sure what my options are here.    |
>|                                                                            |
>|The problem is that graph nodes have nothing in common. Thus there is       |
>|nothing except for the graph traversal operations you could implement on    |
>|the graph as a whole.                                                       |
>|                                                                            |
>|[..]"                                                                       |
>|----------------------------------------------------------------------------|
> 
> You made it sound as if a Visitor Pattern might work.

In which case nodes would be descendants of some common root with the
visitor's accept operation. A common interface would change everything,
however. 

Interesting is that Ada's pool-specific pointers (to class-wide targets)
are a kind of doubly dispatching (pool class x type class), which in the
end allows visitor-like implementations without any common root.

There is another case of hidden double dispatch in Ada. It is stream
attributes T'Class'Input and T'Class'Output (stream class x type class).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 20:06 ` Dmitry A. Kazakov
@ 2009-10-13 10:45   ` Colin Paul Gloster
  2009-10-13 10:17     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 17+ messages in thread
From: Colin Paul Gloster @ 2009-10-13 10:45 UTC (permalink / raw)


On Sun, 11 Oct 2009, Dmitry A. Kazakov wrote:

|----------------------------------------------------------------------------|
|"                                                                           |
|On Sun, 11 Oct 2009 09:41:54 -0700 (PDT), xorque wrote:                     |
|                                                                            |
|> I'd like to develop a program that processes a graph. The contents of     |
|> the graph are a random selection of objects of different types (all       |
|> elements may be of the same type or may all be different - assuming       |
|> there are enough types defined). By 'type' in this case, I am             |
|> referring to Ada types.                                                   |
|>                                                                           |
|> The basic problem is that I want to create an object of a type picked     |
|> at random, at runtime. I'm not entirely sure what my options are here.    |
|                                                                            |
|The problem is that graph nodes have nothing in common. Thus there is       |
|nothing except for the graph traversal operations you could implement on    |
|the graph as a whole.                                                       |
|                                                                            |
|[..]"                                                                       |
|----------------------------------------------------------------------------|

You made it sound as if a Visitor Pattern might work.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-11 16:41 Runtime type selection xorque
                   ` (2 preceding siblings ...)
  2009-10-11 20:06 ` Dmitry A. Kazakov
@ 2009-10-13 15:11 ` xorque
  2009-10-13 15:50   ` Dmitry A. Kazakov
  3 siblings, 1 reply; 17+ messages in thread
From: xorque @ 2009-10-13 15:11 UTC (permalink / raw)


'Lo.

I'm currently still a little lost as to how to use
Ada.Tags.Generic_Dispatching_Constructor
correctly.

I have the following test package:

with Ada.Numerics.Discrete_Random;
with Ada.Tags.Generic_Dispatching_Constructor;
with Ada.Tags;

with Circle;
with Square;

package body Shape_Selector is
  package Tags renames Ada.Tags;

  --
  -- Names associated with types.
  --

  type Shape_Name_t is
    (Shape_Class,
     Circle_Class,
     Square_Class);

  package Shape_Name_Random is new Ada.Numerics.Discrete_Random
    (Result_Subtype => Shape_Name_t);

  Random_Context : Shape_Name_Random.Generator;

  Shape_Names : constant array (Shape_Name_t) of Tags.Tag :=
    (Shape_Class  => Shape.Shape_t'Tag,
     Circle_Class => Circle.Circle_t'Tag,
     Square_Class => Square.Square_t'Tag);

  type Unused_t is null record;

  function Construct
    (Params : not null access Unused_t) return Shape.Shape_t'Class is
  begin
    -- What?!
  end Construct;

  function Dispatching_Constructor is new
Ada.Tags.Generic_Dispatching_Constructor
    (T           => Shape.Shape_t'Class,
     Parameters  => Unused_t,
     Constructor => Construct);

  --
  -- Select a shape at random from Shape_Names.
  --

  function Select_Shape return Shape.Shape_t'Class is
    Shape_Name : constant Shape_Name_t := Shape_Name_Random.Random
(Random_Context);
    Unused     : aliased Unused_t;
  begin
    return Dispatching_Constructor
      (The_Tag => Shape_Names (Shape_Name),
       Params  => Unused'Unchecked_Access);
  end Select_Shape;

end Shape_Selector;

I have selected a Tag at random from the Shape_Names array and have
passed it
to the Dispatching_Constructor procedure but don't know what I'm
supposed to
put in Construct in this case. I don't see how I can know what type
I'm supposed
to be constructing (or how I would, even if I was to pass the Tag via
Params).



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-13 15:11 ` xorque
@ 2009-10-13 15:50   ` Dmitry A. Kazakov
  2009-10-13 16:02     ` xorque
  0 siblings, 1 reply; 17+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-13 15:50 UTC (permalink / raw)


On Tue, 13 Oct 2009 08:11:39 -0700 (PDT), xorque wrote:

> 'Lo.
> 
> I'm currently still a little lost as to how to use
> Ada.Tags.Generic_Dispatching_Constructor
> correctly.
> 
> I have the following test package:
> 
> with Ada.Numerics.Discrete_Random;
> with Ada.Tags.Generic_Dispatching_Constructor;
> with Ada.Tags;
> 
> with Circle;
> with Square;
> 
> package body Shape_Selector is
>   package Tags renames Ada.Tags;
> 
>   --
>   -- Names associated with types.
>   --
> 
>   type Shape_Name_t is
>     (Shape_Class,
>      Circle_Class,
>      Square_Class);
> 
>   package Shape_Name_Random is new Ada.Numerics.Discrete_Random
>     (Result_Subtype => Shape_Name_t);
> 
>   Random_Context : Shape_Name_Random.Generator;
> 
>   Shape_Names : constant array (Shape_Name_t) of Tags.Tag :=
>     (Shape_Class  => Shape.Shape_t'Tag,
>      Circle_Class => Circle.Circle_t'Tag,
>      Square_Class => Square.Square_t'Tag);
> 
>   type Unused_t is null record;
> 
>   function Construct
>     (Params : not null access Unused_t) return Shape.Shape_t'Class is
>   begin
>     -- What?!
>   end Construct;

Construct must be a primitive operation of the class instances of which you
are going to create. Construct must be overridden in each instance and
return this instance's object.

The whole idea of is: given the tag of an instance (concrete type), create
the object of that type using a primitive operation of that type. The
operation is Construct in this case. It must be overridden in each
instance.

Working example:

with Ada.Tags;  use Ada.Tags;
package P is
   type T is abstract tagged limited null record;
   function Create (Params : not null access Integer)
      return T is abstract; -- Abstract constructor
end P;

with Ada.Tags;  use Ada.Tags;
with P;         use P;
package Q is
   type T1 is new T with null record;
   overriding function Create (Params : not null access Integer)
      return T1; -- Implementation of the constructor
   type T2 is new T with null record;
   overriding function Create (Params : not null access Integer)
      return T2;
end Q;

package body Q is
   function Create (Params : not null access Integer)
      return T1 is
   begin
      return (T with null record);
   end Create;
   function Create (Params : not null access Integer)
      return T2 is
   begin
      return (T with null record);
   end Create;
end Q;

with P;  use P;
with Q;  use Q;
with Ada.Tags.Generic_Dispatching_Constructor;
procedure Main is
   function Create is
      new Ada.Tags.Generic_Dispatching_Constructor (T, Integer, Create);
   Parameter : aliased Integer;
   X : T'Class := Create (T1'Tag, Parameter'Access);
       -- Creates T1 using Q.Create
begin
   null;
end Main;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Runtime type selection
  2009-10-13 15:50   ` Dmitry A. Kazakov
@ 2009-10-13 16:02     ` xorque
  0 siblings, 0 replies; 17+ messages in thread
From: xorque @ 2009-10-13 16:02 UTC (permalink / raw)


On Oct 13, 3:50 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> The whole idea of is: given the tag of an instance (concrete type), create
> the object of that type using a primitive operation of that type. The
> operation is Construct in this case. It must be overridden in each
> instance.
>
> Working example:

That makes vastly more sense, thank you.



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2009-10-13 16:02 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-11 16:41 Runtime type selection xorque
2009-10-11 17:02 ` Niklas Holsti
2009-10-11 17:15   ` xorque
2009-10-11 19:54     ` Niklas Holsti
2009-10-12  9:26       ` Georg Bauhaus
2009-10-12 12:02         ` xorque
2009-10-12 23:42       ` Randy Brukardt
2009-10-13  6:50         ` Niklas Holsti
2009-10-13  0:59       ` Adam Beneschan
2009-10-13  7:01         ` Niklas Holsti
2009-10-11 17:15 ` mockturtle
2009-10-11 20:06 ` Dmitry A. Kazakov
2009-10-13 10:45   ` Colin Paul Gloster
2009-10-13 10:17     ` Dmitry A. Kazakov
2009-10-13 15:11 ` xorque
2009-10-13 15:50   ` Dmitry A. Kazakov
2009-10-13 16:02     ` xorque

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox