From: Brian Drummond <brian_drummond@btconnect.com>
Subject: Newbie-ish question about generics and Ada.Streams
Date: Mon, 27 Dec 2010 17:23:53 +0000
Date: 2010-12-27T17:23:53+00:00 [thread overview]
Message-ID: <ohhhh6tr9nit36daakg9m0i6bgq4ug3knp@4ax.com> (raw)
Season's greetings!
In between rounds of turkey, I have been trying to learn a bit more about generics, though it still
feels as if I am pushing on a rope.
In particular, I have been trying to use generic procedures for stream access for a large set of
similar data types (enumerations) where I want a specific representation in the output file. This
means attaching the Read and Write procedures - instantiated generics - to the types using
representation clauses.
Which (as I understand it) has to be done before the types are frozen....
I hope the example below is clear...
Comments welcome, but the specific points I am unhappy with are:
(1) The incomplete procedure declarations, with deferred implementation.
I suspect there is no way around this, as long as I need to freeze the type
before the procedure body.
(2) The second generic parameter - the named array type. It feels like I am missing
something obvious here, and there ought to be a way to avoid adding this clutter.
(3) Instantiating the generic under a different name, and renaming to match the incomplete
declaration. Is this (a) necessary, (b) Gnat-specific, or (c) something stupid on my part?
Thanks,
- Brian
with Ada.Text_Io.Text_Streams;
with Ada.Streams;
procedure try_generics is
-- We have multiple enumerations...
type shape is (circle, square);
type colour is (red, green, blue);
-- and we want to control how they are written to a stream
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
what : in colour);
procedure shape_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
what : in shape);
for colour'write use colour_write;
for shape'write use shape_write;
-- In this example, we use an array of strings indexed by the enumerations.
-- shapes : constant array(shape) of string(1 .. 7) := ("circle ", "square ");
-- but... generics (below) seem picky about using named vs anonymous subtypes
subtype name is string(1 .. 7);
type shape_names is array(shape) of name;
type colour_names is array(colour) of name;
-- appears to freeze the types; write procedures or representation clauses after this are "too late"
shapes : constant shape_names := ("circle ", "square ");
colours : constant colour_names := ("red ", "green ", "blue ");
-- Example body of a write procedure...
--procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
what : in colour) is
--begin
-- String'write(Stream, colours(what));
--end colour_write;
-- That would get repetitive, so let's use a generic...
generic
type Item_Type is (<>);
type Item_Names(<>) is array(Item_Type) of name;
-- Feels as if the Item_Names type declaration ought to be unnecessary...
Names : Item_Names;
procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in Item_Type);
procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in Item_Type) is
begin
String'Write(Stream, Names(Item));
end Enum_Write;
-- And instantiate it. First attempt...
--procedure shape_write is new Enum_Write(Item_Type => shape,
Item_Names => shape_names, Names => shapes);
--try_generics.adb:12:01: missing body for "shape_write"
--try_generics.adb:43:11: instantiation cannot provide body for "shape_write"
-- So instantiate it under a different name, and rename it...
procedure shape_writer is new Enum_Write(Item_Type => shape,
Item_Names => shape_names, Names => shapes);
procedure shape_write(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
what : in shape) renames shape_writer;
procedure colour_writer is new Enum_Write(Item_Type => colour,
Item_Names => colour_names, Names =>colours);
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
what : in colour) renames colour_writer;
-- That duplication is ugly ... can this be simplified?
-- Now we can use the enumerations in a toy block
type toy_block is record
my_colour : colour;
my_shape : shape;
end record;
-- and output the block to a stream
my_block : constant toy_block := (my_colour => red, my_shape => square);
Stdout : Ada.Text_Io.Text_Streams.Stream_Access :=
Ada.Text_Io.Text_Streams.Stream(Ada.Text_Io.Current_Output);
begin
toy_block'write(Stdout, my_block);
end try_generics;
next reply other threads:[~2010-12-27 17:23 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-27 17:23 Brian Drummond [this message]
2010-12-27 18:59 ` Newbie-ish question about generics and Ada.Streams Robert A Duff
2010-12-27 23:26 ` Brian Drummond
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox