Modula-3
A fine programming language, descended (of course) from Modula Two (1985ish)
Strictly speaking, it is descended from Modula-2+. Modula-3 has some additional features: Exceptions, Objects, Garbage collection, Template modules, Partial hiding of type information, Lightweight threads.
Modula-3 makes something different: It uses structural equivalence, that is, if two records contain the same fields with the same names they are equivalent. Thus you can't define two indistinguishable record types simply by defining one twice.
A design goal was to keep the language specification under 50 pages. They overran their page budget by six lines.
Modula 3 is technically not one of the Wirth Languages, because it was not developed by Niklaus Wirth, although it was given his blessing.
There's a Modula-3 resource page at "www.m3.org ". This has moved since 2007 to "modula3.org ". The language definition is at "www.research.compaq.com ".
Simplified Wrapper And Interface Generator (SWIG) can be used to make calls to Cee Language or Cee Plus Plus code.
Shamefully, Java didn't steal nearly enough from it.
[That's right - it stole all everything from Oberon-2 and the Oberon system (another Wirth Languages, but plus an extensible OS) - including the portable object-code idea. (See Oberon Language)] -- Arnold Layne
I can't quite remember the history of the languages, but I do remember seeing Niklaus Wirth at Digital's Systems Research Center quite often.
See:
-- Steve Freeman (who can be very boring on this topic)
Which parts of Modula 3 would you like to see in Java?
Principally the libraries
(the sources www.research.compaq.com are a gold mine of software engineering theory and practice) which were very mature and written by some of the smartest people on the planet. It also has very nice constructs for mixing safe and "native" code, it doesn't just drop you into raw C++ like Java does. Do I need to say anything more about AWT and Swing?... And a bunch of smaller things like its threads interface and decent ordinal types.
That sounds great. Hey, you'd be just the person to ask. One thing that always bugged me in Pascal was the inability to define an ordinal as the union of two other ordinals. There were many times when I needed to say, "This range is exactly the same as that range, except its higher limit is one greater." Or, "this is the same as the set of PrimaryColors, but with the addition of these SecondaryColors. Not being able to do that was a bit of an annoyance in Pascal's type system. Can you do anything like that in Modula 3?
It's been a while, so I'm not sure. I think you can do:
TYPE T = [First .. Last]; TYPE U = [T.First .. T.Last, Extra];
It's so depressing that Csharp Language missed proper ordinals, so you still have to check for bad values in case statements, etc. Sigh.
In Csharp Language Discussion, somebody wrote Hopefully C# uses Modula's model of pointers and addresses, instead of C's confused and confusing model. What model is that?
The Modula language family makes a clear separation between pointers, as a strongly typed, language-level, indirect reference to dynamically allocated objects, and addresses, machine-level indices into the virtual memory of a process. You cannot get a pointer to an object on the stack or in an array or record through the base language. To use addresses, one must import the appropriate standard module that defines the ADDRESS type and functions for taking the address of variables and converting between pointers and addresses or cardinals and addresses. In Modula-3, a module that uses addresses is marked as "unsafe".
C on the other hand doesn't have pass-by-reference parameters, and uses pointers instead. Therefore programs have to get pointers to objects in global memory or on the stack. There is no difference between this kind of pointer and pointers to objects on the heap, which causes extra complication when managing memory. C also allows silent conversions between pointers and addresses, and from arrays to pointers to their first element.
Modula 3 is undoubtedly thought a fine language by most people who choose to use it. To those of us who have had to use it because others chose it, it proved horrendously painful - especially the pointer system. I can remember asking around if people had any ideas on how to make the language worse, and the only suggestions were line numbers and concepts ported from Intercal. Just to let you know that whatever standards are being used here, they aren't universal.
Not having used it, I'm curious: what made it horrendously painful?
In my (brief and unprofessional) experience with Modula-3, it was painful mainly because of brief documentation on the more sophisticated/fun parts (try figuring out exactly how pointers are supposed to work, try figuring out what the limits are on arrays, and how both relate to type declarations, try figuring out how to make dynamic arrays, I didn't even dare touch the OO-ish features) and the amazingly annoying syntax. Some of it is just unfamiliarity; having to declare a separate block to put your variable declarations in isn't something a C/C++ (or OCaml, in my case) programmer is used to. Types and structure constructors can't be imported into modules like functions can (or if they can be, it's undocumented), the formatting functions aren't bad but could be better if there were a few more gaps in the type system, and worst of all is the constant nagging feeling that there actually IS a bloody good language there, lurking beneath all the annoying type constraints and over-verbose ALL IN CAPS syntax.
> horrendously painful - especially the pointer system
Pointers *should* be difficult to use because they're a major source of bugs. You can do everything M3, including function references, except interfacing to external libraries without using pointers.
> try figuring out exactly how pointers are supposed to work
Ok, so they're not so difficult after all.
VAR x:
INTEGER := 100;
address:
ADDRESS := ADR( x );
> try figuring out how to make dynamic arrays
VAR array := NEW( REF ARRAY OF INTEGER, 10 );
> try figuring out what the limits are on arrays
VAR last := LAST( array );
How do you do it in C?
> I didn't even dare touch the OO-ish features
TYPE Class1 = OBJECT (* member vars *) METHODS (* methods *) END; VAR object := NEW( Class1 );
> having to declare a separate block to put your variable declarations in isn't something a C/C++ (or OCaml, in my case) programmer is used to
I don't see the difference between this (Modula-3):
VAR x := 100; BEGIN VAR y := 200; BEGIN (* use x and y here *) END; END;
and this (OCaml):
let x = 100 in let y = 200 in (* use x and y here *) ;;
and even this (C):
int x = 100; int y = 200; /* use x and y here */
which is the same as this (C):
{ int x = 100; { int y = 200; /* use x and y here */ } }
although M3 programmers would more commonly write this:
VAR x:
INTEGER := 100;
y:
INTEGER := 200;
BEGIN (* use x and y here *) END;
> Types and structure constructors can't be imported into modules like functions can (or if they can be, it's undocumented)
In fact 'importing' is one of M3's most documented features. See 'IMPORT' in any M3 reference. For example, create a module that defines a record type:
MODULE Foo; TYPE R1 = RECORD x:
INTEGER; END; END;
Import the module in order to use the type:
MODULE Bar; IMPORT Foo; VAR r1:
Foo.R1; END;
> all the annoying type constraints
You mean like having to declare a variable's type? Function parameter types? Return types? Record and object member types? I'm not sure how this is worse than C/C++.
Or do you mean you'd prefer to have weak typing, like this?
float x = 100.0; char* y = (char*)&x;
But is that really good programming practice? A weak type system is not necessarily a Good Thing.
Or do you not like manifest typing? Again, you can't escape it in C/C++, so I'm not sure what you mean. Implicit typing like you have in OCaml makes typing code easier, but I haven't found that it makes debugging any easier.
If you like implicit typing, you can use it.
VAR x := 100; BEGIN (* use x *) END; WITH x = 100 DO (* use x *) END;
> over-verbose ALL IN CAPS syntax
No, not ALL IN CAPS, but just KEYWORDS in caps. I hated it at first, too, but now I don't even notice it. You can any name you want to declare functions and variables, including 'object', 'array', 'procedure', 'main', 'int', etc. Also, emacs makes the code look reeeeeally pretty.
Heh, I've been trying to say the same thing about Oberon source code too, but they just don't listen. --Samuel A. Falvo II
(by Dejan Lekic, dejan.lekic.org ): Modula-3, like all languages which utilize garbage collector, doesn't expect from developer too much pointer-arithmetic. Also, those developers who know Modula-3 (I am C++ developer myself), know how amazingly Modula-3 is safe. I just want to remind you - all modules who work with pointers are considered unsafe by default.
See original on c2.com