From: eachus@mitre-bedford.arpa (Robert I. Eachus)
Subject: Re: Mutual distrust
Date: 10 Jul 91 22:06:45 GMT [thread overview]
Message-ID: <EACHUS.91Jul10150645@largo.mitre.org> (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...
next reply other threads:[~1991-07-10 22:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
1991-07-10 22:06 Robert I. Eachus [this message]
-- strict thread matches above, loose matches on Subject: below --
1991-07-10 22:17 Mutual distrust cis.ohio-state.edu!magnus.acs.ohio-state.edu!zaphod.mps.ohio-state.edu!ho
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox