n8243274@unicorn.WWU.EDU (steven l. odegard) (10/03/89)
In article <INFO-M2%89093000360807@UCF1VM> Modula2 List <INFO-M2%UCF1VM.BITNET@PSUVM.PSU.EDU> writes: [stuff delted] > Which (algebraically) reads exactly as you mean it. In Ada you can > define the '+' operator to be able to handle the Complex number type. > > Would such a feature be warranted in Modula-2? > Here is some theoretical code: [stuff deleted] May I add my two cents worth to the all desired extensions for a better future language inspired by Wirth's ingenious Modula-2: In addition to IMPORT and EXPORT, modified modula programs will have optional INHERIT and EXHIBIT. These, unlike IMPORT and EXPORT, refer to modifications to the language itself. The syntax for INHERIT and EXHIBIT is similar to that for IMPORT and EXPORT. If operator overloading is to be defined in the current module, i.e. not INHERITed, then first define the procedure and its associated types: IMPLEMENTATION MODULE InternalComplexUseage ; TYPE Complex = RECORD RP, CP : REAL END ; PROCEDURE AddComplex( A, B : Complex ; VAR R : Complex ) ; BEGIN R.RP := A.RP + B.RP ; R.CP := A.CP + B.CP END AddComplex ; Now, overload it to the operator "+". This shall be accomplished by a new block option with the header QUALIFIED. We'll assume here some other operators have also been defined for Complex: QUALIFIED complexad ; AddComplex( A, B : Complex ; VAR R : Complex ) FOR R := A + B ; SubComplex( A, B : Complex ; VAR R : Complex ) FOR R := A - B ; MulComplex( A, B : Complex ; VAR R : Complex ) FOR R := A * B ; DivComplex( A, B : Complex ; VAR R : Complex ) FOR R := A / B ; CopyComplex( A : Complex ; VAR R : Complex ) FOR R := A ; END complexad ; (* ... body omitted *) END InternalComplexUseage . The compiler will now recognize A+B where A and B are Complex, and substitute the appropriate calls. It will also recognize and decompose objects like A*(B+C) + C/(A+B) . Now, if these objects are desired to be used elsewhere, then they must (1) be EXHIBITed from the current module, and (2) INHERITed into the module desired. An INHERITance will automatically import its subsiderary objects. DEFINITION MODULE ComplexDefinitions ; EXPORT Complex, AddComplex, SubComplex, MulComplex, DivComplex ; EXHIBIT complexad ; (* ... definition body omitted, it is as in InternalComplexUseage *) END ComplexDefinitions . (* ... within another module now ... *) MODULE UseComplexDefinitions ; FROM ComplexDefinitions INHERIT complexad ; (* automatically imports |* Complex, AddComplex, etc.; overloads "+", "-", "*", etc. *) (* ... body omitted *) END UseComplexDefinitions . Another example, building on the abstract type defined: IMPLEMENTATION MODULE MatrixDefinitions ; FROM ComplexDefinitions INHERIT complexad ; (* this statement also IMPORTS |* Complex, AddComplex, etc. *) CONST NodeSize = 31 ; TYPE Matrix = POINTER TO MatrixListHead ; MatrixListHead = RECORD Dimensions : RECORD Rows, Columns : CARDINAL ; ChainNumber : CARDINAL ; Current : ARRAY [ 0 .. NodeSize ] OF Complex ; Next : MatrixListHead ; END ; PROCEDURE AddMatrix( A, B : Matrix ; VAR R : Matrix ) ; (* ... body is deleted. *) PROCEDURE SubMatrix( A, B : Matrix ; VAR R : Matrix ) ; (* ... body is delted. *) END MatrixDefinitions . Now, its corresponding definition module is: DEFINITION MODULE MatrixDefinitions ; EXHIBIT QUALIFIED matrixad ; (* perhaps, like EXPORT QUALIFIED, these need |* not be included in a DEFINITION module. *) TYPE Matrix ; (* hidden *) PROCEDURE AddMatrix( A, B : Matrix ; VAR R : Matrix ) ; PROCEDURE SubMatrix( A, B : Matrix ; VAR R : Matrix ) ; PROCEDURE MulMatrix( A, B : Matrix ; VAR R : Matrix ) ; PROCEDURE CopyMatrix( A : Matrix ; VAR R : Matrix ) ; QUALIFIED matrixad ; AddMatrix( A, B : Matrix ; VAR R : Matrix ) FOR R := A + B ; SubMatrix( A, B : Matrix ; VAR R : Matrix ) FOR R := A - B ; MulMatrix( A, B : Matrix ; VAR R : Matrix ) FOR R := A * B ; CopyMatrix( A : Matrix ; VAR R : Matrix ) FOR R := A ; END matrixad ; END MatrixDefinitions . In the same article, we have the proposed body section: >VAR > Result : Complex; > A, B : Complex; > >BEGIN > A := 2.0, 2.0; > B := 4.0, 4.0; > Result := A + B; >END; Here presupposed is the use of structured constants. Like SETs, these should be prefixed with the appropriate structure's name. We require a new form of bracket delimiter indicating this, perhaps <# and #> . Now, then, here is how this should appear: PROCEDURE DefineComplex( A, B : REAL ; VAR C : Complex ) ; QUALIFIED Complexad ; DefineComplex( A, B : REAL ; VAR C : Complex ) FOR C := Complex <# A, B #> ; END Complexad ; Then the body section appears VAR Result : Complex; A, B : Complex; BEGIN A := Complex <# 2.0, 2.0 #> ; B := Complex <# 4.0, 4.0 #> ; Result := A + B; END; I don't propose defining user-defined infix operators at this time. --SLO
UI0T@DKAUNI2.BITNET (Thomas Koenig) (10/04/89)
Here comes another (more or less necessary) view... I think that overloading operators may be nice but not necessary. In my opinion, there is a much simpler solution with pretty much the same effect. How about an extension to the language which would allow functions to return not only predefined types such as integers, reals and so on but also records and arrays? What I'm thinking of could look like this: TYPE COMPLEX= RECORD RE,IM:REAL END; PROCEDURE ADDC(A,B:COMPLEX):COMPLEX; BEGIN B.RE:=B.RE+A.RE; B.IM:=B.IM+A.IM; RETURN B; END ADDC; This would result in expressions like D:=ADDC(MULTC(B,A),DIVC(C,A)); which is, in effect, Polish notation. It would take a little bit of getting used to to read, but it is better than nothing; it also wouldn't need a drastic alteration of the language. In fact, the proposed standard for ANSI-C has required this kind of thing for records (or structures, as they are called in C). Thomas Koenig UI0T@DKAUNI2.BITNET UI0T%DKAUNI2.BITNET@CUNYVM.CUNY.EDU (soon) UI0T@IBM3090.RZ.UNI-KARLSRUHE.DE
abrodnik@WATDRAGON.WATERLOO.EDU ("Andrej Brodnik ", Andy) (10/04/89)
In article <"89-10-03-22:05:28.25*UI0T"@DKAUNI2.BITNET> you write: >Here comes another (more or less necessary) view... > >I think that overloading operators may be nice but not necessary. In my >opinion, there is a much simpler solution with pretty much the same >effect. > >How about an extension to the language which would allow functions to >return not only predefined types such as integers, reals and so on but >also records and arrays? What I'm thinking of could look like this: > Hi! The problem you proposed solution for was already solved in the newest BSI Modula-2 standard. For more information and further reference try to get my paper, which will be presented on the First International Modula-2 Conference, which will be held in Bled, Yugoslavia. The address of the organizing committee is: Ms.Polona Blaznik "Jozef Stefan" Institute, Jamova 39, YU-61000 Ljubljana Yugoslavia phone: +38 61 214-399 fax: +38 61 219-385 tlx: 31-296 yu jostin Best regards Andrej Brodnik PS: They will certainly send you a copy if you would ask them!
lsmith@apollo.HP.COM (Lawrence C. Smith) (10/04/89)
In article <"89-10-03-22:05:28.25*UI0T"@DKAUNI2.BITNET> Modula2 List <INFO-M2%UCF1VM.BITNET@PSUVM.PSU.EDU> writes: >Here comes another (more or less necessary) view... > >I think that overloading operators may be nice but not necessary. In my >opinion, there is a much simpler solution with pretty much the same >effect. > >How about an extension to the language which would allow functions to >return not only predefined types such as integers, reals and so on but >also records and arrays? What I'm thinking of could look like this: > >TYPE COMPLEX= RECORD RE,IM:REAL END; >PROCEDURE ADDC(A,B:COMPLEX):COMPLEX; ... Wirth forgot to restrict results to word-size types in the very first Modula-2 report (the one with the yellow ETH covers). The first compiler implemented to this spec that did not come from Wirth himself was Modula II for the p-System (on Apple II's and ///'s) from a company in California whose name escapes me now. They implemented record types for return values and then put in a switch to disable the feature when Wirth told them it was not supported. Their compiler was written in Pascal, and still lives as the Pecan Modula2 compiler for the p-System. Wirth has some very definite blind spots for language design that really puzzle me in a man so otherwise gifted. You'd think that returning records would be simple, obvious, and orthogonal and so would be one of his top hot buttons. Instead he seems to think they are anathema, and even today he just pays them lip service. Does Oberon allow them? Does it allow them but not implement them? Another of Wirth's blind spots is strings. To get real efficiency with strings you've just gotta have help from the compiler, but Wirth never, ever believed in them. Of course, if you add any of this you no longer have a sub-4000-line compiler. The man quests for small compilers the way Percival sought the Grail. -- Larry Smith Internet: lsmith@apollo.hp.com UUCP: {decvax,mit-eddie,umix}!apollo!lsmith
preston@titan.rice.edu (Preston Briggs) (10/05/89)
In article <46075cda.1199f@apollo.HP.COM> lsmith@apollo.HP.COM (Lawrence C. Smith) writes: >Wirth has some very definite blind spots for language design that really puzzle >me in a man so otherwise gifted. You'd think that returning records would be >simple, obvious, and orthogonal and so would be one of his top hot buttons. >Does Oberon allow them? Does it allow them but not implement them? > >Another of Wirth's blind spots is strings. To get real efficiency with strings >you've just gotta have help from the compiler, but Wirth never, ever believed in >them. >Larry Smith Oberon doesn't allow structured types (records or arrays) to be returned from functions. There's slightly more suport for strings than before. Basically, he's using null-terminated arrays of char, rather like C. However, I think he's correct not to allow functions to return structured values. In fact, I think he should modify his standard parameter passing mechanism to something like: PROCEDURE zap(VAR a, b, c: aType; CON x, y, z: bType); This would allow all structured types to be passed by reference, rather than copying. If you need to copy it later, fine; but not as part of the call. As a bonus, optimizers would be able to do a better job around procedure calls, without the necessity of interprocedural analysis. Overall, I'm down on "hidden" costs arising from copying large arrays and records. Regards, Preston Briggs
lins@Apple.COM (Chuck Lins) (10/05/89)
In article <46075cda.1199f@apollo.HP.COM> lsmith@apollo.HP.COM (Lawrence C. Smith) writes: >In article <"89-10-03-22:05:28.25*UI0T"@DKAUNI2.BITNET> Modula2 List <INFO-M2%UCF1VM.BITNET@PSUVM.PSU.EDU> writes: >>Here comes another (more or less necessary) view... > [Refering to returning records as function results] Oberon specific forbids arrays and records as function results. -- Chuck Lins | "Exit left to funway." Apple Computer, Inc. | Internet: lins@apple.com 20525 Mariani Avenue | AppleLink: LINS Mail Stop 41-K | Cupertino, CA 95014 | "Self-proclaimed Object Oberon Evangelist" I speak for myself and no one else.
lins@Apple.COM (Chuck Lins) (10/05/89)
>However, I think he's correct not to allow functions to return >structured values. In fact, I think he should modify his >standard parameter passing mechanism to something like: > > PROCEDURE zap(VAR a, b, c: aType; > CON x, y, z: bType); > One can simply return records and arrays by specifying them as VAR parameters. If one really wants to specify usage of a parameter you might as well go to Ada's paramater mode specification of either: in, out, or inout. -- Chuck Lins | "Exit left to funway." Apple Computer, Inc. | Internet: lins@apple.com 20525 Mariani Avenue | AppleLink: LINS Mail Stop 41-K | Cupertino, CA 95014 | "Self-proclaimed Object Oberon Evangelist" I speak for myself and no one else.
MARKV@UKANVAX.BITNET ("MARK GOODERUM - UNIV. OF KANSAS ACS - MARKV@UKANVAX") (10/05/89)
I really don't see what the arguement is. If you wan't to return an array or record why not just return the pointer? Visually it is still obvious in the code what you are doing and is fast also. If you want to return a new record or array, then there is NEW or ALLOCATE. -Mark Gooderum MARKV@UKANVAX
UI0T@DKAUNI2.BITNET (Thomas Koenig) (10/05/89)
MARKV@UKANVAX writes: > I really don't see what the arguement is. If you wan't to return an > array or record why not just return the pointer? Visually it is still > obvious in the code what you are doing and is fast also. If you want > to return a new record or array, then there is NEW or ALLOCATE. > > -Mark Gooderum > MARKV@UKANVAX The point is the following: If I have to do, for example, complex arithmetic with complicated formulas, I don't want to have to keep track of what I have allocated in the meantime. (Ever try a Newton iteration with a formula like f(x)=exp((a*x**2+b*x+c)/(d*x+e)) ?) The derivative in the case above is quite complicated, without the added bother of either 1) defining my own stack for calculations 2) using auxilliary variables for intermediate results (I tried that once; the result was a program I could not read although I had written it) 3) allocating space for intermediate results which has to be deallocated later (or else I am going to see some very strange results when space runs out on the heap) 4) keeping track of real and imaginary parts seperately In complicated formulas using complex arithmetic, I don't want to do any of the four above, because the mathematics is bothersome enough without the added complexity of bookkeeping. If I can't do it in Modula, I will do it in FORTRAN or C (FORTRAN because it already has complex arithmetic). I don't want to use either language more than I can help it, because I think Modula is much superior to both of them in almost every respect, but at present, Modula does not leave me much of a choice in such matters. With the possibilities of returning at least records via function values and with of passing multidimensional arrays of varying size to procedures, like level 1 ISO Pascal, which allows the construct procedure something(var a:array[1..n,1..m] of real); , after which the array a and the integers n and m can be accessed, Modula would be my language of choice for numerical work. As it is today, it isn't. Thomas Koenig UI0T@DKAUNI2.BITNET UI0T%DKAUNI2.BITNET@CUNYVM.CUNY.EDU (soon) UI0T@IBM3090.RZ.UNI-KARLSRUHE.DE
firth@sei.cmu.edu (Robert Firth) (10/05/89)
In article <INFO-M2%89100500031512@UCF1VM> Modula2 List <INFO-M2%UCF1VM.BITNET@PSUVM.PSU.EDU> writes: >I really don't see what the arguement is. If you wan't to return an >array or record why not just return the pointer? Visually it is still >obvious in the code what you are doing and is fast also. If you want >to return a new record or array, then there is NEW or ALLOCATE. Leaving aside the efficiency considerations of using dynamic storage needlessly, you still cannot do it this way. The syntax of Modula-2 does not allow the result of a function call to be dereferenced. Yet another mindlessly stupid restriction whose sole purpose seems to be to enforce one person's view of programming style on the world.
tom@MIMS-IRIS.WATERLOO.EDU (Tom Haapanen) (10/06/89)
In article <"89-10-03-22:05:28.25*UI0T"@DKAUNI2.BITNET> you write: > In fact, the proposed > standard for ANSI-C has required this kind of thing for records (or > structures, as they are called in C). No no no ... you should say "this kind of thing for structures (or records, as they are called in Modula-2)". :) :) :) :) \tom haapanen "now, you didn't really expect tom@mims-iris.waterloo.edu my views to have anything to do watmims research group with my employer's, did you?" university of waterloo "I don't even know what street Canada is on" -- Al Capone
MARKV@UKANVAX.BITNET ("MARK GOODERUM - UNIV. OF KANSAS ACS - MARKV@UKANVAX") (10/06/89)
Are you sure about dereferencing. What about this imaginary code fragment: MODULE FakeReturn; VAR FooPtr: POINTER TO StructuredData; PROCEDURE GetStructuredData(Some parameters):ADDRESS; (* Forgot to Import *) (* ADDRESS, oh well..*) BEGIN do some stuff... RETURN(SomeAddress); END GetStructuredData; BEGIN blah blah. FooPtr:=GetStructuredData(blahBlah); AReference:=FooPtr^.SomeElement; END FakeReturn; I know I didn't declare everything, but this is off the top of my head and you get the idea. Now I personally don't see what is wrong with Dynamic allocation, especially for large arrays, records, etc, since it keeps program file size down and speeds load times. In fact I have some programs that are ALL dynamic allocation or local variables since I occasionally need/want to write reeentrant code. Cordially, Mark Gooderum MARKV@UKANVAX
MARKV@UKANVAX.BITNET ("MARK GOODERUM - UNIV. OF KANSAS ACS - MARKV@UKANVAX") (10/06/89)
One other thought about dynamic allocation. You only need to allocate global variables of course, and if you do have an iterative procedure that needs lots of scratch space what about Mark and Release (although not all compilers support this kind of heap management). Other tricks I use to keep track of allocations are software stacks by pushing size and address on a stack and popping the whole stack and deallocating, or singly linked list. But MY big complaint in Modula-2 is lack of easy string support and file handling. If I have a program I want to work with several files I either have to do all the high level stuff myself or be opening and closing files left and right (now THERE is a way to slow down a machine). -Mark
Pat.Terry@p101.f4.n494.z5.fidonet.org (Pat Terry) (10/06/89)
In Message-ID: <"89-10-03-22:05:28.25*UI0T"@DKAUNI2.BITNET> Koenig writes > How about an extension to the language which would allow functions to > return not only predefined types such as integers, reals and so on but > also records and arrays? That's supposed to be in already. Certainly will be in the ISO standard. Some compilres have always had it, others not - usual reason, PIM-2 doesn't discuss it, without saying that records and arrays are wrong either. > TYPE COMPLEX= RECORD RE,IM:REAL END; But if you're proposing an extension, why not propose a proper COMPLEX? -- ----- uucp: { uunet!tektronix | sun!nosun }!qiclab!m2xenix!puddle!5!494!4.101!Pat.Terry Internet: Pat.Terry@p101.f4.n494.z5.fidonet.org