home *** CD-ROM | disk | FTP | other *** search
- Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!newsfeed.internetmci.com!howland.reston.ans.net!surfnet.nl!swsbe6.switch.ch!swidir.switch.ch!epflnews!dinews.epfl.ch!Magnus.Kempe
- From: Magnus.Kempe@di.epfl.ch (Magnus Kempe)
- Newsgroups: comp.lang.ada,comp.answers,news.answers
- Subject: Ada FAQ: Programming with Ada (part 3 of 4)
- Followup-To: poster
- Date: 30 May 1996 17:09:27 GMT
- Organization: None
- Lines: 835
- Sender: magnus@lglsun4.epfl.ch (Magnus Kempe)
- Approved: news-answers-request@MIT.EDU
- Distribution: world
- Message-ID: <4okko7$idt@disunms.epfl.ch>
- Reply-To: Magnus.Kempe@di.epfl.ch (Magnus Kempe)
- NNTP-Posting-Host: lglsun4.epfl.ch
- Mime-Version: 1.0
- Content-Type: text/plain; charset=iso-8859-1
- Content-Transfer-Encoding: 8bit
- Summary: Ada Programmer's Frequently Asked Questions (and answers),
- part 3 of 4.
- Please read before posting.
- Keywords: advanced language, artificial languages, computer software,
- data processing, programming languages, Ada
- Xref: senator-bedfellow.mit.edu comp.lang.ada:45675 comp.answers:18998 news.answers:73084
-
- Archive-name: computer-lang/Ada/programming/part3
- Comp-lang-ada-archive-name: programming/part3
- Posting-Frequency: monthly
- Last-modified: 22 May 1996
- Last-posted: 23 April 1996
-
- Ada Programmer's
- Frequently Asked Questions (FAQ)
-
- IMPORTANT NOTE: No FAQ can substitute for real teaching and
- documentation. There is an annotated list of Ada books in the
- companion comp.lang.ada FAQ.
-
- Recent changes to this FAQ are listed in the first section after the table
- of contents. This document is under explicit copyright.
-
- This is part 3 of a 4-part posting; part 1 contains the table of contents.
- Part 2 begins with question 5.
- Part 4 begins with question 9.
- Parts 1 and 2 should be the previous postings in this thread.
- Part 4 should be the next posting in this thread.
-
-
- 6: Ada Numerics
-
-
- 6.1: Where can I find anonymous ftp sites for Ada math packages? In particular
- where are the random number generators?
-
-
- ftp.rational.com
- Freeware version of the ISO math packages on Rational's FTP
- server. It's a binding over the C Math library, in
- public/apex/freeware/math_lib.tar.Z
-
- archimedes.nosc.mil
- Stuff of high quality in pub/ada The random number generator
- and random deviates are recommended. These are mirrored at the
- next site, wuarchive.
-
- wuarchive.wustl.edu
- Site of PAL, the Public Ada Library: math routines scattered
- about in the directories under languages/ada in particular, in
- subdirectory swcomps
-
- source.asset.com
- This is not an anonymous ftp site for math software. What you
- should do is log on anonymously under ftp, and download the
- file asset.faq from the directory pub. This will tell you how
- to get an account.
-
- ftp.cs.kuleuven.ac.be
- Go to directory pub/Ada-Belgium/cdrom. There's a collection of
- math intensive software in directory swcomps. Mirrors some of
- PAL at wuarchive.wustl.edu.
-
- sw-eng.falls-church.va.us
- Go to directory public/AdaIC/source-code/bindings/ADAR-bindings
- to find extended-precision decimal arithmetic (up to 18
- digits). Includes facilities for COBOL-like formatted output.
-
-
- 6.2: How can I write portable code in Ada 83 using predefined types like Float
- and Long_Float? Likewise, how can I write portable code that uses Math
- functions like Sin and Log that are defined for Float and Long_Float?
-
- (from Jonathan Parker)
-
- Ada 83 was slow to arrive at a standard naming convention for
- elementary math functions and complex numbers. Furthermore, you'll
- find that some compilers call the 64-bit floating point type
- Long_Float; other compilers call it Float. Fortunately, it is easy to
- write programs in Ada that are independent of the naming conventions
- for floating point types and independent of the naming conventions of
- math functions defined on those types.
-
- One of the cleanest ways is to make the program generic:
-
- generic
- type Real is digits <>;
- with function Arcsin (X : Real) return Real is <>;
- with function Log (X : Real) return Real is <>;
- -- This is the natural log, inverse of Exp(X), sometimes written Ln(X).
- package Example_1 is
- ...
- end Example_1;
-
-
- So the above package doesn't care what the name of the floating point
- type is, or what package the Math functions are defined in, just as
- long as the floating point type has the right attributes (precision
- and range) for the algorithm, and likewise the functions. Everything
- in the body of Example_1 is written in terms of the abstract names,
- Real, Arcsin, and Log, even though you instantiate it with compiler
- specific names that can look very different:
-
- package Special_Case is new Example_1 (Long_Float, Asin, Ln);
-
-
- The numerical algorithms implemented by generics like Example_1 can
- usually be made to work for a range of floating point precisions. A
- well written program will perform tests on Real to reject
- instantiations of Example_1 if the floating points type is judged
- inadequate. The tests may check the number of digits of precision in
- Real (Real'Digits) or the range of Real (Real'First, Real'Last) or the
- largest exponent of the set of safe numbers (Real'Safe_Emax), etc.
- These tests are often placed after the begin statement of package
- body, as in:
-
- package body Example_1 is
- ...
- begin
- if (Real'Machine_Mantissa > 60) or (Real'Machine_Emax < 256) then
- raise Program_Error;
- end if;
- end Example_1;
-
-
- Making an algorithm as abstract as possible, (independent of data
- types as much as possible) can do a lot to improve the quality of the
- code. Support for abstraction is one of the many things Ada-philes
- find so attractive about the language. The designers of Ada 95
- recognized the value of abstraction in the design of numeric
- algorithms and have generalized many of the features of the '83 model.
- For example, no matter what floating point type you instantiate
- Example_1 with, Ada 95 provides you with functions for examining the
- exponent and the mantissas of the numbers, for truncating, determining
- exact remainders, scaling exponents, and so on. (In the body of
- Example_1, and in its spec also of course, these functions are
- written, respectively: Real'Exponent(X), Real'Fraction(X),
- Real'Truncation(X), Real'Remainder(X,Y), Real'Scaling(X, N). There are
- others.) Also, in package Example_1, Ada 95 lets you do the arithmetic
- on the base type of Real (called Real'Base) which is liable to have
- greater precision and range than type Real.
-
- It is rare to see a performance loss when using generics like this.
- However, if there is an unacceptable performance hit, or if generics
- cannot be used for some other reason, then subtyping and renaming will
- do the job. Here is an example of renaming:
-
- with Someones_Math_Lib;
- procedure Example_2 is
-
- subtype Real is Long_Float;
-
- package Math renames Someones_Math_Lib;
- function Arcsin(X : Real) return Real renames Math.Asin
- function Log (X : Real) return Real renames Math. Ln;
-
- -- Everything beyond this point is abstract with respect to
- -- the names of the floating point (Real), the functions (Arcsin
- -- and Log), and the package that exported them (Math).
- ...
- end Example_2;
-
-
- I prefer to make every package and subprogram (even test procedures)
- as compiler independent and machine portable as possible. To do this
- you move all of the renaming of compiler dependent functions and all
- of the "withing" of compiler dependent packages to a single package.
- In the example that follows, its called Math_Lib_8. Math_Lib_8 renames
- the 8-byte floating point type to Real_8, and makes sure the math
- functions follow the Ada 95 standard, at least in name. In this
- approach Math_Lib_8 is the only compiler dependent component.
-
- There are other, perhaps better, ways also. See for example, "Ada In
- Action", by Do-While Jones for a generic solution.
-
- Here's the spec of Math_Lib_8, which is a perfect subset of package
- Math_Env_8, available by FTP in file
- ftp://lglftp.epfl.ch/pub/Ada/FAQ/math_env_8.ada
-
-
- --***************************************************************
- -- Package Math_Lib_8
- --
- -- A minimal math package for Ada 83: creates a standard interface to vendor
- -- specific double-precision (8-byte) math libraries. It renames the 8 byte
- -- Floating point type to Real_8, and uses renaming to create
- -- (Ada 95) standard names for Sin, Cos, Log, Sqrt, Arcsin, Exp,
- -- and Real_8_Floor, all defined for Real_8.
- --
- -- A more ambitious but perhaps less efficient
- -- package would wrap the compiler specific functions in function calls, and
- -- do error handling on the arguments to Ada 95 standards.
- --
- -- The package assumes that Real_8'Digits > 13, and that
- -- Real_8'Machine_Mantissa < 61. These are asserted after the
- -- begin statement in the body.
- --
- -- Some Ada 83 compilers don't provide Arcsin, so a rational-polynomial+
- -- Newton-Raphson method Arcsin and Arccos pair are provided in the body.
- --
- -- Some Ada 83 compilers don't provide for truncation of 8 byte floats.
- -- Truncation is provided here in software for Compilers that don't have it.
- -- The Ada 95 function for truncating (toward neg infinity) is called 'Floor.
- --
- -- The names of the functions exported below agree with the Ada9X standard,
- -- but not, in all likelihood the semantics. It is up to the user to
- -- be careful...to do his own error handling on the arguments, etc.
- -- The performance of these function can be non-portable,
- -- but in practice they have their usual meanings unless you choose
- -- weird arguments. The issues are the same with most math libraries.
- --***************************************************************
-
- --with Math_Lib; -- Meridian DOS Ada.
- with Long_Float_Math_Lib; -- Dec VMS
- --with Ada.Numerics.Generic_Elementary_Functions; -- Ada9X
- package Math_Lib_8 is
-
- --subtype Real_8 is Float; -- Meridian 8-byte Real
- subtype Real_8 is Long_Float; -- Dec VMS 8-byte Real
-
- --package Math renames Math_Lib; -- Meridian DOS Ada
- package Math renames Long_Float_Math_Lib; -- Dec VMS
- --package Math is new Ada.Numerics.Generic_Elementary_Functions(Real_8);
-
- -- The above instantiation of the Ada.Numerics child package works on
- -- GNAT, or any other Ada 95 compiler. Its here if you want to use
- -- an Ada 95 compiler to compile Ada 83 programs based on this package.
-
- function Cos (X : Real_8) return Real_8 renames Math.Cos;
- function Sin (X : Real_8) return Real_8 renames Math.Sin;
- function Sqrt(X : Real_8) return Real_8 renames Math.Sqrt;
- function Exp (X : Real_8) return Real_8 renames Math.Exp;
-
- --function Log (X : Real_8) return Real_8 renames Math.Ln; -- Meridian
- function Log (X : Real_8) return Real_8 renames Math.Log; -- Dec VMS
- --function Log (X : Real_8) return Real_8 renames Math.Log; -- Ada 95
-
- --function Arcsin (X : Real_8) return Real_8 renames Math.Asin; -- Dec VMS
- --function Arcsin (X : Real_8) return Real_8 renames Math.Arcsin; -- Ada 95
- function Arcsin (X : Real_8) return Real_8;
- -- Implemented in the body. Should work with any compiler.
-
- --function Arccos (X : Real_8) return Real_8 renames Math.Acos; -- Dec VMS
- --function Arccos (X : Real_8) return Real_8 renames Math.Arccos; -- Ada 95
- function Arccos (X : Real_8) return Real_8;
- -- Implemented in the body. Should work with any compiler.
-
- --function Real_8_Floor (X : Real_8) return Real_8 renames Real_8'Floor;-- 95
- function Real_8_Floor (X : Real_8) return Real_8;
- -- Implemented in the body. Should work with any compiler.
-
- end Math_Lib_8;
-
-
- 6.3: Is Ada any good at numerics, and where can I learn more about it?
-
- First of all, a lot of people find the general Ada philosophy
- (modularity, strong-typing, readable syntax, rigorous definition and
- standardization, etc.) to be a real benefit in numerical programming,
- as well as in many other types of programming. But Ada --and
- especially Ada 95-- was also designed to meet the special requirements
- of number-crunching applications.
-
- The following sketches out some of these features. Hopefully a little
- of the flavor of the Ada philosophy will get through, but the best
- thing you can do at present is to read the two standard reference
- documents, the Ada 95 Rationale and Reference Manual. Below the GNU
- Ada 95 compiler is referred to several times. This compiler can be
- obtained by anonymous FTP from cs.nyu.edu, and at mirror sites
- declared in the README file of directory pub/gnat.
-
- 1. Machine portable floating point declarations. (Ada 83 and Ada 95)
- If you declare "type Real is digits 14", then type Real will
- guarantee you (at least) 14 digits of precision independently
- of machine or compiler. In this case the base type of type Real
- will usually be the machine's 8-byte floating point type. If an
- appropriate base type is unavailable (very rare), then the
- declaration is rejected by the compiler.
-
- 2. Extended precision for initialization of floating point. (Ada 83
- and Ada 95)
- Compilers are required to employ
- extended-precision/rational-arithmetic routines so that
- floating point variables and constants can be correctly
- initialized to their full precision.
-
- 3. Generic packages and subprograms. (Ada 83 and Ada 95)
- Algorithms can be written so that they perform on abstract
- representations of the data structure. Support for this is
- provided by Ada's generic facilities (what C++ programmers
- would call templates).
-
- 4. User-defined operators and overloaded subprograms. (Ada 83 and Ada
- 95)
- The programmer can define his own operators (functions like
- "*", "+", "abs", "xor", "or", etc.) and define any number of
- subprograms with the same name (provided they have different
- argument profiles).
-
- 5. Multitasking. (Ada 83 and Ada 95)
- Ada facilities for concurrent programming (multitasking) have
- traditionally found application in simulations and
- distributed/parallel programming. Ada tasking is an especially
- useful ingredient in the Ada 95 distributed programming model,
- and the combination of the two makes it possible to design
- parallel applications that have a high degree of operating
- system independence and portability. (More on this in item 6
- below.)
-
- 6. Direct support for distributed/parallel computing in the language.
- (Ada 95)
- Ada 95 is probably the first internationally standardized
- language to combine in the same design complete facilities for
- multitasking and parallel programming. Communication between
- the distributed partitions is via synchronous and asynchronous
- remote procedure calls.
-
- Good discussion, along with code examples, is found in the
- Rationale, Part III E, and in the Ada 95 Reference Manual,
- Annex E. See also "Ada Letters", Vol. 13, No. 2 (1993), pp. 54
- and 78, and Vol. 14, No. 2 (1994), p. 80. (Full support for
- these features is provided by compilers that conform to the Ada
- 95 distributed computing Annex. This conformance is optional,
- but for instance GNAT, the Gnu Ada 95 compiler, will meet these
- requirements.)
-
- 7. Attributes of floating point types. (Ada 83 and Ada 95)
- For every floating point type (including user defined types),
- there are built-in functions that return the essential
- characteristics of the type. For example, if you declare "type
- Real is digits 15" then you can get the max exponent of objects
- of type Real from Real'Machine_Emax. Similarly, the size of the
- Mantissa, the Radix, the largest Real, and the Rounding policy
- of the arithmetic are given by Real'Machine_Mantissa,
- Real'Machine_Radix, Real'Last, and Real'Machine_Rounds. There
- are many others.
-
- (See Ada 95 Reference Manual, clause 3.5, subclause 3.5.8 and
- A.5.3, as well as Part III sections G.2 and G.4.1 of the Ada 95
- Rationale.)
-
- 8. Attribute functions for floating point types. (Ada 95)
- For every floating point type (including user defined types),
- there are built-in functions that operate on objects of that
- type. For example, if you declare "type Real is digits 15" then
- Real'Remainder (X, Y) returns the exact remainder of X and Y: X
- - n*Y where n is the integer nearest X/Y. Real'Truncation(X),
- Real'Max(X,Y), Real'Rounding(X) have the usual meanings.
- Real'Fraction(X) and Real'Exponent(X) break X into mantissa and
- exponent; Real'Scaling(X, N) is exact scaling: multiplies X by
- Radix**N, which can be done by incrementing the exponent by N,
- etc. (See citations in item 7.)
-
- 9. Modular arithmetic on integer types. (Ada 95)
- If you declare "type My_Unsigned is mod N", for arbitrary N,
- then arithmetic ("*", "+", etc.) on objects of type My_Unsigned
- returns the results modulo N. Boolean operators "and", "or",
- "xor", and "not" are defined on the objects as though they were
- arrays of bits (and likewise return results modulo N). For N a
- power of 2, the semantics are similar to those of C unsigned
- types.
-
- 10. Generic elementary math functions for floating point types. (Ada
- 95)
- Required of all compilers, and provided for any floating point
- type: Sqrt, Cos, Sin, Tan, Cot, Exp, Sinh, Cosh, Tanh, Coth,
- and the inverse functions of each of these, Arctan, Log,
- Arcsinh, etc. Also, X**Y for floating point X and Y. Compilers
- that conform to the Numerics Annex meet additional accuracy
- requirements.
-
- (See subclause A.5.1 of the Ada 95 RM, and Part III, Section
- A.3 of the Ada 95 Rationale.)
-
- 11. Complex numbers. (Ada 95)
- Fortran-like, but with a new type called Imaginary. Type
- "Imaginary" allows programmers to write expressions in such a
- way that they are easier to optimize, more readable and appear
- in code as they appear on paper. Also, the ability to declare
- object of pure imaginary type reduces the number of cases in
- which premature type conversion of real numbers to complex
- causes floating point exceptions to occur. (Provided by
- compilers that conform to the Numerics Annex. The Gnu Ada 95
- compiler supports this annex, so the source code is freely
- available.)
-
- 12. Generic elementary math functions for complex number types. (Ada
- 95)
- Same functions supported for real types, but with complex
- arguments. Standard IO is provided for floating point types and
- Complex types. (Only required of compilers that support the
- Numerics Annex, like Gnu Ada.)
-
- 13. Pseudo-random numbers for discrete and floating point types. (Ada
- 95)
- A floating point pseudo-random number generator (PRNG) provides
- output in the range 0.0 .. 1.0. Discrete: A generic PRNG
- package is provided that can be instantiated with any discrete
- type: Boolean, Integer, Modular etc. The floating point PRNG
- package and instances of the (discrete) PRNG package are
- individually capable of producing independent streams of random
- numbers. Streams may be interrupted, stored, and resumed at
- later times (generally an important requirement in
- simulations). In Ada it is considered important that multiple
- tasks, engaged for example in simulations, have easy access to
- independent streams of pseudo random numbers. The Gnu Ada 95
- compiler provides the cryptographically secure X**2 mod N
- generator of Blum, Blum and Shub.
-
- (See subclause A.5.2 of the Ada 95 Reference Manual, and part
- III, section A.3.2 of the Ada Rationale.)
-
- 14. Well-defined interfaces to Fortran and other languages. (Ada 83
- and Ada 95)
- It has always been a basic requirement of the language that it
- provide users a way to interface Ada programs with foreign
- languages, operating system services, GUI's, etc. Ada can be
- viewed as an interfacing language: its module system is
- composed of package specifications and separate package bodies.
- The package specifications can be used as strongly-type
- interfaces to libraries implemented in foreign languages, as
- well as to package bodies written in Ada. Ada 95 extends on
- these facilities with package interfaces to the basic data
- structures of C, Fortran, and COBOL and with new pragmas. For
- example, "pragma Convention(Fortran, M)" tells the compiler to
- store the elements of matrices of type M in the Fortran
- column-major order. (This pragma has already been implemented
- in the Gnu Ada 95 compiler. Multi- lingual programming is also
- a basic element of the Gnu compiler project.) As a result,
- assembly language BLAS and other high performance linear
- algebra and communications libraries will be accessible to Ada
- programs.
-
- (See Ada 95 Reference Manual: clause B.1 and B.5 of Annex B,
- and Ada 95 Rationale: Part III B.)
-
-
- 6.4: How do I get Real valued and Complex valued math functions in Ada 95?
-
- (from Jonathan Parker)
-
- Complex type and functions are provided by compilers that support the
- numerics Annex. The packages that use Float for the Real number and
- for the Complex number are:
-
- Ada.Numerics.Elementary_Functions;
- Ada.Numerics.Complex_Types;
- Ada.Numerics.Complex_Elementary_Functions;
-
-
- The packages that use Long_Float for the Real number and for the
- Complex number are:
-
- Ada.Numerics.Long_Elementary_Functions;
- Ada.Numerics.Long_Complex_Types;
- Ada.Numerics.Long_Complex_Elementary_Functions;
-
-
- The generic versions are demonstrated in the following example. Keep
- in mind that the non-generic packages may have been better tuned for
- speed or accuracy. In practice you won't always instantiate all three
- packages at the same time, but here is how you do it:
-
- with Ada.Numerics.Generic_Complex_Types;
- with Ada.Numerics.Generic_Elementary_Functions;
- with Ada.Numerics.Generic_Complex_Elementary_Functions;
-
- procedure Do_Something_Numerical is
-
- type Real_8 is digits 15;
-
- package Real_Functions_8 is
- new Ada.Numerics.Generic_Elementary_Functions (Real_8);
-
- package Complex_Nums_8 is
- new Ada.Numerics.Generic_Complex_Types (Real_8);
-
- package Complex_Functions_8 is
- new Ada.Numerics.Generic_Complex_Elementary_Functions
- (Complex_Nums_8);
-
- use Real_Functions_8, Complex_Nums_8, Complex_Functions_8;
- ...
- ... -- Do something
- ...
- end Do_Something_Numerical;
-
-
- 6.5: What libraries or public algorithms exist for Ada?
-
- An Ada version of Fast Fourier Transform is available. It's in
- journal "Computers & Mathematics with Applications," vol. 26, no. 2,
- pp. 61-65, 1993, with the title:
-
- "Analysis of an Ada Based Version of Glassman's General N Point Fast
- Fourier Transform"
-
- The package is now available in the AdaNET repository, object #: 6728,
- in collection: Transforms. If you're not an AdaNET user, contact Peggy
- Lacey (lacey@rbse.mountain.net).
-
- _________________________________________________________________
-
-
- 7: Efficiency of Ada Constructs
-
-
- 7.1: How much extra overhead do generics have?
-
- If you overgeneralize the generic, there will be more work to do for
- the compiler. How do you know when you have overgeneralized? For
- instance, passing arithmetic operations as parameters is a bad sign.
- So are boolean or enumeration type generic formal parameters. If you
- never override the defaults for a parameter, you probably
- overengineered.
-
- Code sharing (if implemented and requested) will cause an additional
- overhead on some calls, which will be partially offset by improved
- locality of reference. (Translation, code sharing may win most when
- cache misses cost most.) If a generic unit is only used once in a
- program, code sharing always loses.
-
- R.R. Software chose code sharing as the implementation for generics
- because 2 or more instantiations of Float_Io in a macro implementation
- would have made a program too large to run in the amount of memory
- available on the PC machines that existed in 1983 (usually a 128k or
- 256k machine).
-
- Generics in Ada can also result in loss of information which could
- have helped the optimizer. Since the compiler is not restricted by Ada
- staticness rules within a single module, you can often avoid penalties
- by declaring (or redeclaring) bounds so that they are local:
-
- package Global is
- subtype Global_Int is
- Integer range X..Y;
-
- ...
- end Global;
-
-
- with Global;
- package Local is
- subtype Global_Int is
- Global.Global_Int;
-
- package Some_Instance is
- new Foo (Global_Int);
-
- ...
- end Local;
-
-
- Ada rules say that having the subtype redeclared locally does not
- affect staticness, but on a few occasions optimizers have been caught
- doing a much better job. Since optimizers are constantly changing,
- they may have been caught just at the wrong time.
-
-
- 7.2: How does Ada compare to other languages in efficiency of code?
-
- Ada vs. C: An analysis at Tartan found that Ada and C had fairly
- similar performance, with Ada having a slight edge. See "C vs. Ada:
- Arguing Performance Religion" by David Syiek, ACM Ada Letters, Nov/Dec
- 1995 (Volume XV Number 6), pp. 67-69.
-
- Ada vs. assembly language: There is a documented case where an Ada
- compiler and a novice Ada programmer did better than experienced
- assembly language programmers. See "Ada Whips Assembly" by Elam and
- Lawlis, Crosstalk, March 1992. Published by the Software Technology
- Support Center, Hill Air Force Base, Utah: Defense Printing Service.
-
- _________________________________________________________________
-
- 8: Advanced Programming Techniques with Ada
-
-
- 8.1: How can I redefine the assignment operation?
-
- The general answer is: use controlled types (RM95-7.6).
-
- For detailed explanations, read the following papers:
- * "Tips and Tidbits #1: User Defined Assignment" by Brad Balfour,
- HTML at http://www.acm.org/~bbalfour/tips_no_1.html
- * "Abstract Data Types Are Under Full Control with Ada 9X" by Magnus
- Kempe, Postscript file at
- http://lglwww.epfl.ch/Ada/Resources/Papers/OO/ADT_Control-revised.ps
-
-
- 8.2: Does Ada have automatic constructors and destructors?
-
- Yes, controlled types have special, user-definable operations that
- control the construction and destruction of objects and values of
- those types (see question 8.1, above).
-
- (Also: Tucker Taft replies)
- At least in Ada 9X, functions with controlling results are inherited
- (even if overriding is required), allowing their use with dynamic
- binding and class-wide types. In most other OOPs, constructors can
- only be called if you know at compile time the "tag" (or equivalent)
- of the result you want. In Ada 9X, you can use the tag determined by
- the context to control dispatching to a function with a controlling
- result. For example:
-
- type Set is abstract tagged private;
- function Empty return Set is abstract;
- function Unit_Set(Element : Element_Type) return Set is abstract;
- procedure Remove(S : in out Set; Element : out Element_Type) is abstract;
- function Union(Left, Right : Set) return Set is abstract;
- ...
-
- procedure Convert(Source : Set'Class; Target : out Set'Class) is
- -- class-wide "convert" routine, can convert one representation
- -- of a set into another, so long as both set types are
- -- derived from "Set," either directly or indirectly.
-
- -- Algorithm: Initialize Target to the empty set, and then
- -- copy all elements from Source set to Target set.
-
- Copy_Of_Source : Set'Class := Source;
- Element : Element_Type;
- begin
- Target := Empty; -- Dispatching for Empty determined by Target'Tag.
-
- while Copy_Of_Source /= Empty loop
- -- Dispatching for Empty based on Copy_Of_Source'Tag
-
- Remove_Element(Copy_Of_Source, Element);
-
- Target := Union(Target, Unit_Set(Element));
- -- Dispatching for Unit_Set based on Target'Tag
- end loop;
- end Convert;
-
-
- The functions Unit_Set and Empty are essentially "constructors" and
- hence must be overridden in every extension of the abstract type Set.
- However, these operations can still be called with a class-wide
- expected type, and the controlling tag for the function calls will be
- determined at run-time by the context, analogous to the kind of
- (compile-time) overload resolution that uses context to disambiguate
- enumeration literals and aggregates.
-
-
- 8.3: Should I stick to a one package, one type approach while writing Ada
- software?
-
- (Robb Nebbe responds)
-
- Offhand I can think of a couple of advantages arising from Ada's
- separation of the concepts of type and module.
-
- Separation of visibility and inheritance allows a programmer to
- isolate a derived type from the implementation details of its parent.
- To put it another way information hiding becomes a design decision
- instead of a decision that the programming language has already made
- for you.
-
- Another advantage that came "for free" is the distinction between
- subtyping and implementation inheritance. Since modules and types are
- independent concepts the interaction of the facilities for information
- hiding already present in Ada83 with inheritance provide an elegant
- solution to separating subtyping from implementation inheritance. (In
- my opinion more elegant than providing multiple forms of inheritance
- or two distinct language constructs.)
-
-
- 8.4: What is the "Beaujolais Effect"?
-
- The "Beaujolais Effect" is detrimental, and language designers should
- try to avoid it. But what is it?
-
- (from Tucker Taft)
-
- The term "Beaujolais Effect" comes from a prize (a bottle of
- Beaujolais) offered by Jean Ichbiah during the original Ada design
- process to anyone who could find a situation where adding or removing
- a single "use" clause could change a program from one legal
- interpretation to a different legal interpretation. (Or equivalently,
- adding or removing a single declaration from a "use"d package.)
-
- At least one bottle was awarded, and if the offer was still open, a
- few more might have been awarded during the Ada 9X process. However,
- thanks to some very nice analysis by the Ada 9X Language Precision
- Team (based at Odyssey Research Associates) we were able to identify
- the remaining cases of this effect in Ada 83, and remove them as part
- of the 9X process.
-
- The existing cases in Ada 83 had to do with implicit conversion of
- expressions of a universal type to a non-universal type. The rules in
- Ada 9X are subtly different, making any case that used to result in a
- Beaujolais effect in Ada 83, illegal (due to ambiguity) in Ada 9X.
-
- The Beaujolais effect is considered "harmful" because it is expected
- that during maintenance, declarations may be added or removed from
- packages without being able to do an exhaustive search for all places
- where the package is "use"d. If there were situations in the language
- which resulted in Beaujolais effects, then certain kinds of changes in
- "use"d packages might have mysterious effects in unexpected places.
-
- (from Jean D. Ichbiah)
-
- It is worth pointing that many popular languages have Beaujolais
- effect: e.g. the Borland Pascal "uses" clause, which takes an
- additive, layer-after-layer, interpretation of what you see in the
- used packages (units) definitely exhibits a Beaujolais effect.
-
- Last time I looked at C++, my impression was that several years of
- Beaujolais vintage productions would be required.
-
- For component-based software development, such effects are undesirable
- since your application may stop working when you recompile it with the
- new -- supposedly improved -- version of a component.
-
-
- 8.5: What about the "Ripple Effect"?
-
- (Tucker Taft explains)
-
- We have eliminated all remnants of the Beaujolais Effect, but we did
- debate various instances of the "Ripple" effect during the language
- revision process (apologies to Gallo Ripple Wine enthusiasts ;-).
-
- In brief, the (undesirable) Ripple effect was related to whether the
- legality of a compilation unit could be affected by adding or removing
- an otherwise unneeded "with" clause on some compilation unit on which
- the unit depended, directly or indirectly.
-
- This issue came up at least twice. One when we were considering rules
- relating to use of attributes like 'Address. In Ada 83 as interpreted
- by the ARG, if a compilation unit contains a use of 'Address, then
- there must be a "with" of package System somewhere in the set of
- library unit specs "with"ed by the compilation unit (directly or
- indirectly).
-
- In Ada 9X, we have eliminated this rule, as it was for some compilers
- an unnecessary implementation burden, and didn't really provide any
- value to the user (if anything, it created some confusion). The rule
- now is that the use of an attibute that returns a value of some
- particular type makes the compilation unit semantically dependent on
- the library unit in which the type is declared (whether or not it is
- "with"ed).
-
- The second place the Ripple effect came up was when we were trying to
- provide automatic direct visibility to (primitive) operators.
- Ultimately we ended up with an explicit "use type" clause for making
- operators directly visible. For a while we considered various rules
- that would make all primitive operators directly visible; some of the
- rules considered created the undesirable "Ripple" effects; others
- created annoying incompatibilities; all were quite tricky to implement
- correctly and efficiently.
-
-
- 8.6: How to write an Ada program to compute when one has had too much alcohol
- to legally drive?
-
- Someone asked if there is an Ada archive of this sort of program. Each
- drink has a number of units of alcohol, max legal level, etc.
-
- (from Bob Kitzberger :-)
-
- Oh, this is much to vague. Don't touch that whizzy development
- environment until you fully analyze the problem domain (unless that
- whizzy development environment includes Rose, in which case, you get
- to avoid paper and pencil from the git-go).
-
- Let's see, we have several classes to describe before we get to the
- implementation:
-
- Person
- subclass Drinker
-
- attributes: weight, age, timeline for amount consumed
-
- Drink
- attributes: percentage of alcohol, quantity of drink
-
- Country
- attributes: legal age to drink; max legal level of alcohol in
- blood
-
-
- Turn on the stereo, perhaps the Brandenburg Concertos. Then, flesh out
- the domain classes. Then, have a Belgian beer and consider what to do
- next. You decide on implementing these classes in a simple way,
- leading to your first successful prototype. Then, have another beer
- and decide what to do next. "Identify risk areas" you mutter to
- yourself, and off you go...
-
- If the beer wasn't too strong, you'd probably realize that the only
- thing of any difficulty in this is the amount consumed / rate of
- decay. Decide on investigating this aspect further. Create
- implementation classes for this and include a reference from the
- Drinker class to this new timeline/decay Class. Have another beer.
- Implement your second prototype. Congratulate yourself for making
- progress so quickly.
-
- Have another beer. Wander over to the stereo and change the CD to
- something more in the mood, maybe some Hendrix or Stevie Ray Vaughn.
- Back in front of the computer; pop another beer. Decide that it would
- be very cool if each drink was its own subclass of drink, and start
- cataloguing every drink out of your "Pocket Bartender's Guide". Have a
- slightly muddled epiphany that you really should create a class for
- each kind of alcohol (vodka, tequila, etc.) and the individual drink
- classes should each multiply inherit from all relevant Alcohol
- classes. Ooh, this is going to be a bit rough, so you have another
- beer. Draw a few of the hundreds of new class relationships needed,
- put that on the back burner when you think "persistence! that's what's
- missing!" Change the CD to Kraftwerk. Start your PPP connection, ask
- the people on comp.object for recommendations on a good OODBMS to use
- to keep track of all of those persistent objects. Make many many typos
- in your posting; everyone ignores it. Fall asleep on the keyboard.
-
-
- 8.7: Does Ada have macros?
-
- No, neither Ada 83 nor Ada 95 do. There was a Steelman requirement
- that the language developed NOT have a macro capability. This was a
- well thought-out requirement. What you see in a piece of Ada code is
- what you get (within a debugger for example). This does not hold true
- for macro languages.
-
- General text-substitution macros like those in the C preprocessor are
- thought to be too unsafe. For example, a macro can refer to a variable
- X and depending where the macro is expanded X may or may not be
- visible. Ada programs are supposed to be readable and in many cases C
- macros are the main culprits in producing unreadable C programs.
-
- Compile time macro facilities tend to be dreadfully over- and misused,
- resulting in horrible maintenance problems. Furthermore, there is a
- tendency to use macros to patch up glaring omissions in the language.
- For example, C has no named constants, a very bad omission, but
- #define is used to patch over this gap.
-
- In C, three "legitimate" uses of macros are for defining compile-time
- constants, types, and inline functions. Ada has all three of these
- facilities, without macros.
-
- If one wants macros to handle conditional compilation, the better way
- to achieve the equivalent is in most instances to isolate the system
- dependent parts and then put them in separate units with multiple
- system-specific implementations.
-