From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,9642027a78f96963,start X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news4.google.com!feeder.news-service.com!216.196.110.144.MISMATCH!border3.nntp.ams.giganews.com!Xl.tags.giganews.com!border1.nntp.ams.giganews.com!nntp.giganews.com!local2.nntp.ams.giganews.com!nntp.bt.com!news.bt.com.POSTED!not-for-mail NNTP-Posting-Date: Mon, 27 Dec 2010 11:22:24 -0600 From: Brian Drummond Newsgroups: comp.lang.ada Subject: Newbie-ish question about generics and Ada.Streams Date: Mon, 27 Dec 2010 17:23:53 +0000 Reply-To: brian@shapes.demon.co.uk Message-ID: X-Newsreader: Forte Agent 1.7/32.534 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Usenet-Provider: http://www.giganews.com X-AuthenticatedUsername: NoAuthUser X-Trace: sv3-JT6HmuONGLKDbHTfvQDwtNIM9/BQ0OWKYC3vmuxctEUn9brDxI/BH51RD8R0/H+9zmUXDFqrcTgGi3z!YEgO3WZfgk1J3WNBKySFJPIiB3MwXj8ahkl2Z46em/uBWii7pYe66tH+rD5C72iD3RGu1iyg6LvS!Sg== X-Complaints-To: abuse@btinternet.com X-DMCA-Complaints-To: abuse@btinternet.com X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 X-Original-Bytes: 5562 Xref: g2news2.google.com comp.lang.ada:17128 Date: 2010-12-27T17:23:53+00:00 List-Id: 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;