comp.lang.ada
 help / color / mirror / Atom feed
* Re: Mutual distrust
@ 1991-07-10 22:06 Robert I. Eachus
  0 siblings, 0 replies; 2+ messages in thread
From: Robert I. Eachus @ 1991-07-10 22:06 UTC (permalink / raw)


In article <6883@ns-mx.uiowa.edu> jones@pyrite.cs.uiowa.edu (Douglas W. Jones,2
01H MLH,3193350740,3193382879) writes:

   Here's a problem I've come up against in designing a simulation
   program voluntarily written in Ada...  The problem: Each PLACE must
   have an associated set of people who occupy that PLACE, and each
   PERSON must know what place he (or she) is in and what other people
   occupy that same place.  This implies a cyclic relationship between
   the packages GEOGRAPHY and POPULATION.

   The one simplifying factor is that there is only one place in which it is
   necessary for the PLACE occupied by a PERSON to be known, and that is
   inside the action routines applied to that particular PERSON, which are
   inside POPULATION.

   Here are the possible solutions I thought up:

   1) Add a third package -- something of a relational package that associates
       people with places, so that given a PLACE it can supply the set of all
       people there, and given a PERSON, it can tell what PLACE that person
       occupies.

       This has the advantage of allowing GEOGRAPHY and POPULATION to be
       completely independant, but because PERSON and PLACE are private
       types, there is no way I can think of to efficiently implement this
       third package.

-- There is an easy way to do this using the Tucker Taft amendment,
-- which allows an incomplete type declaration in a private part to be
-- completed in the body of the package...

    package POPULATION is
      type PERSON is private;
      -- operrations on PERSONs not explicitly involving PLACEs.
      ...
    private
      type PERSON_RECORD;
      type PERSON is access PERSON_RECORD;
    end POPULATION;

    package GEOGRAPHY is
      type PLACE is private;
      -- operations on PLACEs not explicitly involving people.
      ...
    private
      type PLACE_RECORD is private;
      type PLACE is access PLACE_RECORD;
    end GEOGRAPHY;

    with POPULATION; with GEOGRAPHY;
    package PEOPLE_AND_PLACES is
      -- operations involving both people and places...
    end PEOPLE_AND_PLACES;

    with POPULATION; with GEOGRAPHY;
    package HIDDEN is
      type REAL_PERSON is record...
      type REAL_PLACE is record...
      function GET_REAL(P: in POPULATION.PERSON) return REAL_PERSON;
      function GET_REAL(P: in GEOGRAPHY.PLACE) return REAL_PLACE;
    end HIDDEN;

    with UNCHECKED_CONVERSION;
    package body HIDDEN is
      type PERSON_POINTER is access REAL_PERSON;
      function CONVERT is new UNCHECKED_CONVERSION
          (POPULATION.PERSON, PERSON_POINTER);

      function GET_REAL(P: in POPULATION.PERSON) return REAL_PERSON is
      begin return CONVERT(P); end GET_REAL;
      -- do the same for PLACEs
      ...
    end HIDDEN;

    with HIDDEN; 
    package body GEOGRAPHY is
      type PLACE_RECORD is new HIDDEN.REAL_PLACE;

--     Now you can see the actual record declarations in POPULATION,
-- GEOGRAPHY, and PEOPLE_AND_PLACES (assuming that these bodies and
-- only these bodies say with HIDDEN.   Revising either of the record
-- structures will require recompiling the bodies of all three
-- packages but you would have to recomile two of them anyway.
-- However, the only specification which requires recompilation is
-- that for HIDDEN. 

--     I usually only advocate packages like HIDDEN as a way of
-- minimizing recompilations, but sometimes it has other advantages.

   2) Take advantage of the simplifying factor, which allows the following
       package dependancy to be established...

       This is the solution I ended up using, but I don't like the assymetry
       of it, and I don't like what I have to do to it to allow OCCUPANT to
       return a set of people instead of a single PERSON.

--       What's the problem? Have two functions one, call it COUNT,
-- returns the number of residents and the other, OCCUPANTS, returns an
-- array of PERSONs.  The loop which processes this may have to use a
-- different trick... Let's say that POPULATION.PEOPLE is an array
-- (POSITIVE range <>) of PERSON.

         loop
           SOMEPLACE := ...
           -- get next location
           declare
             SOMEPEOPLE: constant POPULATION.PEOPLE :=
					 OCCUPANTS(SOMEPLACE); 
           begin
             for I in SOMEPEOPLE'RANGE loop
               PROCESS(SOMEPEOPLE(I));
             end loop;
           end;
         end loop;

--      The constant keyword is the magic cookie which allows you to
-- declare SOMEPEOPLE without supplying the range.  Since PERSON is an
-- access type, PROCESS is allowed to change fields of the various
-- records but not to assign a new access value to SOMEPEOPLE(I).
--

					Robert I. Eachus

with STANDARD_DISCLAIMER;
use  STANDARD_DISCLAIMER;
function MESSAGE (TEXT: in CLEVER_IDEAS) return BETTER_IDEAS is...

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

* Re: Mutual distrust
@ 1991-07-10 22:17 cis.ohio-state.edu!magnus.acs.ohio-state.edu!zaphod.mps.ohio-state.edu!ho
  0 siblings, 0 replies; 2+ messages in thread
From: cis.ohio-state.edu!magnus.acs.ohio-state.edu!zaphod.mps.ohio-state.edu!ho @ 1991-07-10 22:17 UTC (permalink / raw)


>From article <EACHUS.91Jul10150645@largo.mitre.org>,
by eachus@largo.mitre.org (Robert I. Eachus):
> 
> 2) Take advantage of the simplifying factor, which allows the following
>     package dependancy to be established...
> 
>     This is the solution I ended up using, but I don't like the assymetry
>     of it, and I don't like what I have to do to it to allow OCCUPANT to
>     return a set of people instead of a single PERSON.
> 
> --       What's the problem? ...

The problem turns out to have been a classic Ada problem -- I was casually
equating the concepts of package and abstract data type.  Someone kindly
pointed this out to me by E-mail, and everything fell into place.

What I did was have the package POPULATION export both PERSON and PEOPLE,
where PEOPLE is an abstract set of PERSON.  The type PEOPLE is quite
handy within POPULATION, it is the type returned by OCCUPANT( PLACE ),
and it is reasonable to implement it by renaming a generic instantiation
of a set or list package within POPULATION.

Making the set of people in a separate package from POPULATION that
depends on POPULATION was clearly wrong, and my casual equation of
package with abstract data type prevented me from seeing that both the
singular and set types should be exported from the same package.

					Doug Jones
					jones@cs.uiowa.edu

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

end of thread, other threads:[~1991-07-10 22:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1991-07-10 22:17 Mutual distrust cis.ohio-state.edu!magnus.acs.ohio-state.edu!zaphod.mps.ohio-state.edu!ho
  -- strict thread matches above, loose matches on Subject: below --
1991-07-10 22:06 Robert I. Eachus

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