The ModulaTor Erlangen's First Independent Modula_2 Journal! Nr. 7/Aug-1991 _____________________________________________________________ How to improve acceptance of ISO-Modula_2? by Guenter Dotzel, ModulaWare Whether ISO-Modula_2 will gain acceptance by the programmer community depends on many factors. There are some design decissions in the ISO-Modula_2 language as well as in its standard library made by the international standardisation comittee which gives ISO-Modula_2 the appearance of an academic exercise (i.e. over-engineered). 1. To start with the language's name: Modula-2 is not a valid identifier in Modula-2; it has to be renamed to Modula_2 (just a joke). 2. My request to the Modula_2-DIN-standardisation working group to rename/shorten some of the ISO-Modula_2 library modules' names to a convenient name length was rejected. We now have the module names SYSTEM, COROUTINES, EXCEPTIONS, Termination, Storage, CharClass, Processes, Semaphores, Strings, RealMath, LongMath, ComplexMath, LongComplexMath, WholeIO, RealIO, LongIO, TextIO, BinIO, IORes, SWholeIO, SRealIO, SLongIO, STextIO, SBinIO, SIORes, StdChans, ProgramArgs, SeqStream, RndFile, RewFile, Terminal, IOLink, DevConsts, IOChannel, IOConsts, LowReal, LowLong, ConvTypes, WholeConv, RealConv, LongConv, SysClock. Besides the fact, that there are too many modules, the name length problem and some other aspects are discussed in the following. 3. My request to introduce unique names for the mathematical functions in different modules was rejected. 4. My request to add a pervasive conversion function from COMPLEX to LONGCOMPLEX data type was rejected. You could easily define these functions yourself; of course, by getting some performance loss compared to a build-in function: PROCEDURE CTOLC (c: COMPLEX): LONGCOMPLEX; BEGIN RETURN CMPLX(LFLOAT(RE(c)), LFLOAT(IM(c))); END CTOLC; PROCEDURE LCTOC (c: LONGCOMPLEX): COMPLEX; BEGIN RETURN CMPLX(FLOAT(RE(c)), FLOAT(IM(c))); END LCTOC; If you define these functions CTOLC and LCTOC in every module where such conversions are needed you'll end up in stupid repetitions. On the other hand, if you define these functions in a utility library module, you are free to call them RCMPLX and LCMPLX or ConvertComplexToLongComplex and ConvertLongComplexToComplex. What are your favorite names? For all other data types, there exist build-in conversion functions except for [LONG]COMPLEX. So why did ISO-M2 exclude them? Answer by the comittee: (1) those functions are easily implemented by any programmer and (2) both functions are rarely needed. How could they know? 5. My request to add hyperbolic functions in the mathematical libraries was rejected, since it would be easy for the programmer, to define these functions using exp. This is not true, except for certain trivial argument ranges! If you try to implement sinh, cosh, tanh using the mathematical definitions of a textbook, you'll get rounding errors in certain argument ranges, which make the functions useless. It is especially difficult to implement a correct tanh. To illustrate how complicated tanh is, I like to show my recursive implementation in Modula_2 (no warranty is given! Does anybody have a simpler method except for using LONGREAL internally?): PROCEDURE tanh( R1 : REAL ): REAL; VAR e2, x2, LO,B, tanhLO, x: REAL; CONST (*HIn=1.0/2.0+n/16.0+1.0/32.0; TanHIn=tanh(HIn); Cn=1-TanHIn*TanHIn*) HI0=0.53125; TanHI0=0.48633604; C0=1.0-TanHI0*TanHI0; HI1=0.59375; TanHI1=0.53258728; C1=1.0-TanHI1*TanHI1; HI2=0.65625; TanHI2=0.57586240; C2=1.0-TanHI2*TanHI2; HI3=0.71875; TanHI3=0.61613440; C3=1.0-TanHI3*TanHI3; HI4=0.78125; TanHI4=0.65342359; C4=1.0-TanHI4*TanHI4; HI5=0.84375; TanHI5=0.68779020; C5=1.0-TanHI5*TanHI5; HI6=0.90625; TanHI6=0.71932749; C6=1.0-TanHI6*TanHI6; HI7=0.96875; TanHI7=0.74815444; C7=1.0-TanHI7*TanHI7; r3=-1.0/3.0; r5=2.0/15.0; r7=-17.0/315.0; r9=62.0/2835.0; BEGIN x:=ABS(R1); IF x < 0.0002441406 THEN RETURN R1 ELSIF x < 0.5 THEN x2 := x*x; RETURN (((r9*x2+r7)*x2+r5)*x2+r3)*x2*R1+R1 ELSIF x<HI0 THEN LO:=R1-HI0; tanhLO:=tanh(LO); B:=1.0+TanHI0*tanhLO; RETURN TanHI0+tanhLO*C0/B; ELSIF x<HI1 THEN LO:=R1-HI1; tanhLO:=tanh(LO); B:=1.0+TanHI1*tanhLO; RETURN TanHI1+tanhLO*C1/B; ELSIF x<HI2 THEN LO:=R1-HI2; tanhLO:=tanh(LO); B:=1.0+TanHI2*tanhLO; RETURN TanHI2+tanhLO*C2/B; ELSIF x<HI3 THEN LO:=R1-HI3; tanhLO:=tanh(LO); B:=1.0+TanHI3*tanhLO; RETURN TanHI3+tanhLO*C3/B; ELSIF x<HI4 THEN LO:=R1-HI4; tanhLO:=tanh(LO); B:=1.0+TanHI4*tanhLO; RETURN TanHI4+tanhLO*C4/B; ELSIF x<HI5 THEN LO:=R1-HI5; tanhLO:=tanh(LO); B:=1.0+TanHI5*tanhLO; RETURN TanHI5+tanhLO*C5/B; ELSIF x<HI6 THEN LO:=R1-HI6; tanhLO:=tanh(LO); B:=1.0+TanHI6*tanhLO; RETURN TanHI6+tanhLO*C6/B; ELSIF x<HI7 THEN LO:=R1-HI7; tanhLO:=tanh(LO); B:=1.0+TanHI7*tanhLO; RETURN TanHI7+tanhLO*C7/B; ELSIF x < 10.0 THEN e2 := exp( 2.0 * R1 ); RETURN ( e2 - 1.0 ) / ( e2 + 1.0 ); ELSIF R1 >= 0.0 THEN RETURN 1.0 ELSE RETURN -1.0 END; END tanh; The comittee has two arguments against the addition of hyperbolic functions: (1) if a programmer has problems to implement a correct tanh, she/he would also have other serious numerical problems in her/his application program and last but not least, (2) to let room for the software market of add-on libraries. But what about programmers simply porting software from another language to Modula_2? Should portation work be done only by specialists in numerics or should the numerically-untrained programmer buy add-on libraries. What about the quality of add-on library modules? Are ISO-M2 add-on library supplier required to deliver ISO-M2 like semantic definitions? Do they handle exceptions consistently? 6. The length of module names: Especially the module name LongComplexMath is too long. Instead the M2-DIN-group decided to rename LongMath to LongRealMath to be systematic in naming the modules (but the ISO-group did not follow that decision for the 4th WD). Now both names are too long! So why shouldn't we rename SeqStream, RndFile, RewFile to SequentialFile, RandomFile, RewindableFile, when module name length is not an issue? The problem with long module names is, that if you import e.g. sin from LongMath and also from LongComplexMath in the same module and if the functions contained in different libraries have identical names, you must use one of the functions in qualified mode, e.g.: r := sin(rx); c := LongComplexmath.sin(cx); The latter form is unacceptable, since it is too long and makes the program unreadable. The argument against shortening names was that the programmer could easily IMPORT LongComplexMath; FROM RealMath IMPORT sin; and define CONST dcsin = LongComplexMath.sin; The constant declaration above is procedure renaming in ISO-M2 (a feature which is controversial itself, because a procedure name isn't a constant). For an application programmer this would be a nightmare. Shown below is the complete mathematical library defined this way. IMPORT RealMath, LongMath, ComplexMath, LongComplexMath; TYPE (* enumerations *) RMathException = RealMath.RMathException; dRMathException = LongMath.RMathException; (* both types above are defined identically, but are incompatible *) CMathLibException = ComplexMath.CMathLibException; dCMathLibException = LongComplexMath.CMathLibException; (* both types above are defined identically, but are incompatible *) CONST (* constants *) pi = RealMath.PI; (* RR-type, could be used with LongMath *) exp1 = RealMath.Exp1; (* RR-type, could be used with LongMath *) CONST (* CC-types, can be used with LongComplexMath (i = CMPLX (0.0, 1.0);) *) ci = ComplexMath.i; (* or would you prefer simply i or c_i? *) czero = ComplexMath.zero; cone = ComplexMath.one; CONST (* procedures *) sqrt = RealMath.sqrt; (* or would you prefer sqrt, d_sqrt, c_scrt, dc_sqrt*) dsqrt = LongMath.sqrt; csqrt = ComplexMath.sqrt; dcsqrt = LongComplexMath.sqrt; exp = RealMath.exp; dexp = LongMath.exp; cexp = ComplexMath.exp; dcexp = LongComplexMath.exp; ln = RealMath.ln; dln = LongMath.ln; cln = ComplexMath.ln; dcln = LongComplexMath.ln; sin = RealMath.sin; dsin = LongMath.sin; csin = ComplexMath.sin; dcsin = LongComplexMath.sin; cos = RealMath.cos; dcos = LongMath.cos; ccos = ComplexMath.cos; dccos = LongComplexMath.cos; tan = RealMath.tan; dtan = LongMath.tan; ctan = ComplexMath.tan; dctan = LongComplexMath.tan; arcsin = RealMath.arcsin; darcsin = LongMath.arcsin; carcsin = ComplexMath.arcsin; dcarcsin = LongComplexMath.arcsin; arccos = RealMath.arccos; darccos = LongMath.arccos; carccos = ComplexMath.arccos; dcarccos = LongComplexMath.arccos; arctan = RealMath.arctan; darctan = LongMath.arctan; carctan = ComplexMath.arctan; dcarctan = LongComplexMath.arctan; power = RealMath.power; dpower = LongMath.power; cpower = ComplexMath.power; dcpower = LongComplexMath.power; round = RealMath.round; dround = LongMath.round; cabs = ComplexMath.abs; dcabs = LongComplexMath.abs; carg = ComplexMath.arg; dcarg = LongComplexMath.arg; conj = ComplexMath.conj; dconj = LongComplexMath.conj; cpolar = ComplexMath.polarToComplex; dcpolar = LongComplexMath.polarToComplex; cscalarMult = ComplexMath.scalarMult; dcscalarMult = LongComplexMath.scalarMult; MathException = RealMath.MathException; dMathException = LongMath.MathException; cMathException = ComplexMath.MathException; dcMathException = LongComplexMath.MathException; Should the programmer include the definitions needed at the top of her/his program. Or shoud she/he create a definition module possibly called Math, which contains the complete math library? Should everybody do so if she/he doesn't like to define things more than once? So why shouldn't ISO-M2 include such a definition to get unique and identical names accross all implementations? __________________________________________________________________________________________________ Report from the Sixth ISO SC22/WG13 Modula_2 Working Group Meeting by Guenter Dotzel, ModulaWare GmbH The sixth ISO-Modula_2 working group meeting, attended by 30 members from 14 different countries was helt at the University of Tuebingen from July 1. to 5., 1991. This is a short summary of the most important changes and addition to the 4th Interim ISO-Modula_2 Working Draft Proposal that have been agreed upon at this meeting. The new document produced by the so-called drafters is called the 4th Working Draft (CD10514-2) and shall be ready in Sep-1991. After a voting period of three months, there will be a six months review period before the final paper, called the BFD (big fat document) can be produced. 0. Requirements The minimal requirements for a conforming compiler implementation (such as minimum nesting level for procedure declarations) were defined. These values depend on the size of WORD. 1. Language changes BITSET previously moved to module SYSTEM is now again a pervasive type. 2. I/O-Library identifier renamings 4th Interim WD ----> 4th WD ___________________________________ type IOConsts.ReadResultEnum ---> ReadResults type DevConsts.OpenResultEnum ---> OpenResults type DevConsts.FlagEnum ---> ChanFlags module DevConsts ---> ChanConsts module Terminal ---> TermFile module [S]BinIO ---> [S]RawIO module [S]IORes ---> [S]IOResult module SeqStream ---> StreamFile module RewStream ---> SeqFile procedure [S]TextIO.ReadLine ---> ReadRestLine procedure [S]TextIO.ReadLn ---> SkipLine procedure [S]TextIO.LongIO.ReadLong ---> ReadReal procedure [S]TextIO.LongIO.WriteLong ---> WriteReal procedure [S]TextIO.LongIO.WriteLongFloat ---> WriteFloat procedure [S]TextIO.LongIO.WriteLongFixed ---> WriteFixed procedure [S]TextIO.LongIO.WriteLongEnd ---> WriteEng type RndFile.RndFileExceptionEnum ---> RndFileExceptions procedure IOChannel.BadChan ---> InvalidChan procedure IOChannel.BinRead ---> RawRead procedure IOChannel.BinWrite ---> RawWrite parameter of IOChannel.TextWrite chars ---> charsToWrite parameter of IOChannel.BinWrite/RawWrite locs ---> locsToWrite type IOChannel.ChanExceptionsEnum ---> ChanExceptions type IOChannel.Flags ---> CurrentFlags module IOChannel ---> IOChan procedure ProgramArgs.ArgGiven ---> IsArgPresent Furthermore, module IOChannel is no longer responsible for closing all open channels at program termination. 3. Module Strings Constant BigStringCapacity and type BigString deleted 4. Language extension & modules Exceptions and Termination The syntax of Modula-2 for module block and block was extended by the keywords EXCEPT and FINISH and a new statement RETRY for the except-part. module block = declarations, ["BEGIN", statement sequence ["FINISH", statement sequence] ["EXCEPT", statement sequence] ], "END"; block = declarations, "BEGIN", statement sequence ["EXCEPT", statement sequence], "END"; The procedures EXCEPTIONS.POPHANDLER, PUSHHANDLER, RETRY and ACKNOWLEDGE and the procedure Termination.RegisterCleanUp were deleted. 5. Language extension & module SYSTEM - new constant BITSPERLOC added - type BITNUM and constant BITSPERBITSET removed - new keyword PACKEDSET that is can be used instead of SET to define a bit set (with defined mapping of 2 0 = bit 0). The minimal number of set elements in PACKEDSET shall be equivalent to the size of the largest pervasive type (e.g. 128 with LONG- COMPLEX) - type BITSET is defined as PACKEDSET OF [0..BITSPERLOC*LOCSPERWORD-1] The mapping of bits in bit sets is now defined in terms of an abstract binary number system. This solves the bit mapping consistency accross implementations for both, little- and big-endian machines. - SHIFT and ROTATE apply only to packed sets and must work on at least BITSET - ADDRESSVALUE may cause an exception - ADDADR, SUBADR and DIFADR accept parameters of type ADDRESS and pointers - type BYTE should be provided if appropriate for the machine - note, that neither procedures nor function from module SYSTEM can be assigned to a variable or equated to a constant identifier. 6. Module CharClass PROCEDURE IsWhiteSpace (ch: CHAR): BOOLEAN was added; it returns true if ch is either a space character or a member of an implemenation-defined set of format effector characters. 7. String Conversions Three modules from an earlier proposal (D106) were added. Now there are six modules: three high-level modules WholeStr, RealStr and LongStr that provide simple string conversions (the parameters nextIndex and alignment were dropped) and three low-level modules WholeConv, RealConv and LongConv that provide the so-called scanner modell which is more flexible but not as easy to use as the *Str procedures. In the *Conv modules, the procedure names Scan, Format and Value were renamed to reflect the parameter type, e.g. RealConv.Scan is renamed in ScanReal. The procedures Take and Give were removed, because their functionality is provided in the higher-level *Str modules. 8. The Complex Math-Library was extended and now includes abs, arg, conj, power, sqrt, exp, ln, sin, cos, tan, arcsin, arccos, arctan, polarToComplex, scalarMult, but still no hyperbolic functions. 9. An example using the ISO-Modula_2 I/O-Library of the 4th working draft The program asks for a file name, opens a text file for reading, reads one real number per line from a text file and displays the numbers on the terminal using the so-called simple I/O-modules SLongIO and STextIO that write directly to the standard output channel. Note, that there is no end-of-file equivalent which would allow to write WHILE NOT Eof (cid) DO ... END. MODULE IO_Library_Example; (* uses the 4th working draft of ISO-Modula_2, 11-Jul-1991 *) FROM IOResult IMPORT ReadResults, ReadResult; FROM StreamFile IMPORT read, text, ChanId, Open, Close, OpenResults; FROM TextIO IMPORT SkipLine; FROM LongIO IMPORT ReadReal; FROM STextIO IMPORT ReadRestLine, WriteString, WriteLn; FROM SLongIO IMPORT WriteReal; CONST width = 10; VAR cid: ChanId; filename: ARRAY[0..254] OF CHAR; ores: OpenResults; rres: ReadResults; long: LONGREAL; BEGIN REPEAT WriteString('Please enter a filename'); ReadRestLine(filename); WriteLn; IF LENGTH(filename)=0 THEN RETURN END; Open(cid, filename, read + text, ores); UNTIL ores = opened; LOOP ReadReal(cid, long); IF ReadResult(cid) <> allRight THEN EXIT END; SkipLine(cid); WriteLong(long, width); WriteLn; END; Close(cid); END IO_Library_Example. __________________________________________________________________________________________________ LECTOR/PostScript, File dw2:isotue.dw2, 14-Oct-1991.
IMPRESSUM: The ModulaTor is an unrefereed journal. Technical papers are to be
taken as working papers and personal rather than organizational statements.
Items are printed at the discretion of the Editor based upon his judgement on
the interest and relevancy to the readership. Letters, announcements, and
other items of professional interest are selected on the same basis. Office of
publication: The Editor of The ModulaTor is Guenter Dotzel; he can be reached
by tel/fax: [removed due to abuse] or by
mailto:[email deleted due to spam]
ModulaWare home page The ModulaTor download