* Ada OO Mechanism @ 1999-05-20 0:00 Shawn M. Root 1999-05-20 0:00 ` Samuel Mize 1999-05-21 0:00 ` Dale Stanbrough 0 siblings, 2 replies; 116+ messages in thread From: Shawn M. Root @ 1999-05-20 0:00 UTC (permalink / raw) Greetings, I've been lurking on this newsgroup for about a year now and would first like to thank all of you who contribute to this group regularly for your very interesting and informative discussions. These discussions have led me to a better, though still very limited, understanding of Ada. I would like to ask a question, however. In a recent thread entitled "A question for my personal knowledge" some people were saying that the Ada OO mechanism was counterintuitive. I tend to agree. This concern was dismissed by others as being merely "syntactic sugar", and claims were made that the Ada mechanism is actually easier to use than the C++ style. These arguments seemed misplaced to me. I thought that one of the goals of Ada was to focus on the reader of the code, not the writer. Therefore if this "syntactic sugar" makes code easier to understand, then it would be a good thing, right? Perhaps I've missed the point, but it seems like a Class construct would fit in well with the Ada way of doing things. It seems like a logical evolution from a package, to a generic package, to a class. The syntax would even be similar since (at least where I work) use clauses are rarely used. We write Package_Name.Procedure; so what's wrong with Class_Name.Method; Maybe I just don't understand the issues. I would appreciate any help in making this clear. Thanks. -- Shawn M. Root ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 Ada OO Mechanism Shawn M. Root @ 1999-05-20 0:00 ` Samuel Mize 1999-05-20 0:00 ` David Botton 1999-05-24 0:00 ` Hyman Rosen 1999-05-21 0:00 ` Dale Stanbrough 1 sibling, 2 replies; 116+ messages in thread From: Samuel Mize @ 1999-05-20 0:00 UTC (permalink / raw) Original post rearranged a little. Shawn M. Root <smroot@orbitworld.net> wrote: > ... some people were saying > that the Ada OO mechanism was counterintuitive. I tend to agree. ... >Perhaps I've missed > the point, but it seems like a Class construct would fit in well with > the Ada way of doing things. It seems like a logical evolution from a > package, to a generic package, to a class. First off, the class construct is used in other popular languages, so your argument is not without merit. It would be familiar, and its existence would ease the transition from those other languages. However, Ada already had some of the features that were added to other languages by object-oriented extensions. (Not to name any names, but it's initial is "C".) For instance, the "class" in C++ is the construct for object-oriented programming. It's also the construct for encapsulation of related functions, user definition and extension of types, and templates. But, except for OO programming, all of these were ALREADY in Ada. So the designers of Ada 95 were faced with a dilemma: should they introduce a familiar-looking set of "OO" features that duplicate existing features of the language, or should they introduce only the new features needed to make Ada 83 completely OO-capable, when it was already almost an OOP language to start with? For fair or foul, they took the second path. I personally think it was the right technical decision, but it creates a PR difficulty because people think that the C++ way is the "right" OO way. In fact, it's ONE approach to OO technology -- neither the best nor the worst, but certainly the most popular at present. I feel that the Ada 95 team made the right technical decision because it kept the language features more orthogonal -- that is, we didn't wind up with a bunch of different features doing the same thing. Also, as you stray from the strict C++ model, you find that it's much easier to define your abstractions clearly in Ada. For instance, you don't need a "friends" capability, because encapsulation is not provided by object classes. There are two areas where I've seen strongly-held objections to the Ada model: 1. There isn't a "class" construct that encloses the definition of a class. First note that in Ada terms, we aren't talking about a class, but about a type. A C++ "class" defines a template for data storage, and a set of operations on instances of that template. In Ada, this is a type. In Ada terminology, a "class" is a family of types. That's why a "class-wide" parameter can accept a value of a given type OR any of its descendants: that's an Ada "class." In C++ terms, it can accept a value of a given class or any subclass of that class. Anyway, in Ada, if you want to encapsulate the type definition with its primitive operations, you put a package around it. It just doesn't use the word "class," but it achieves exactly the same thing as a C++ class definition. The advantage to the Ada approach appears when classes are tightly coupled. The standard example is an OO type and an active iterator over that type. The iterator needs to see the "innards" of the other type. In C++ you have to define the iterator class as a "friend" of the other class. In Ada you can simply encapsulate both types in the same package, or with the iterator as a child package. There are other OO design approaches that are harder to implement in C++ than in Ada, because C++ strongly supports one specific view of object-oriented technology. I personally think it would be useful to define some pragma or comment-flag tags that will encode, in the code, what design approach is being used. Some things could be checked for you that are not currently checked, and an ASIS-based tool could look through the compiled results, find what design approach was intended for a given chunk of code, and check those specific constraints. Other people have reacted violently against this idea, for reasons I did not find clear. It seemed they were arguing that not all code should conform to the C++ model, and I certainly agree. I do think it would be useful to encode whether or not a given tagged type was designed to that model, or to another model, and that the compiler suite could check it against the constraints of whatever model it was designed against. But anyway, my overall point is that encapsulation of a type with its primitive operations (in C++ terms, a class) is done with the encapsulation operator in Ada, which is the package. A C++-style "class" would be a redundant encapsulation operator. 2. You can't use "object.method" notation. This is another case where the Ada design gives less support to one specific view of OO technology, because it's supporting more views of OO technology. Specifically, the C++ model is that one object "receives a message" and operates on it, and this is modeled with a function call. The Ada model is, loosely, that a function call identifies an action to occur (or a message, if you prefer), a set of related information (the non-controlling parameters), and a set of objects. These objects, all of the same class, cooperate somehow to accomplish the action (or respond to the message). So, if you want to design using a specific "recipient" for each "message," you can do so. One common approach for this is to use the first parameter for the "recipient." You don't get to call out the recipient as part of the syntax, but on the other hand you don't have to arbitrarily pick one "recipient" if you aren't using that model of object interaction. > This > concern was dismissed by others as being merely "syntactic sugar", and > claims were made that the Ada mechanism is actually easier to use than > the C++ style. These arguments seemed misplaced to me. I thought that > one of the goals of Ada was to focus on the reader of the code, not the > writer. Therefore if this "syntactic sugar" makes code easier to > understand, then it would be a good thing, right? I hope I've clarified the point that, in some cases, the syntax you are talking about would become LESS clear, not clearer. The argument is really whether the language should specifically support one model of OO technology, to the detriment of other models, simply because the currently-most-popular OO language uses that model. > The syntax would even be > similar since (at least where I work) use clauses are rarely used. > We write > Package_Name.Procedure; > so what's wrong with > Class_Name.Method; Nothing. In fact, you can do that now with a one-class-per-package approach, and I don't think you can do it in C++. I note that people who want "object.method" notation often refer to it as "class.method" notation. This suggests to me that their objection is not based in the structure or meaning of the facility, but is about the code having an unfamiliar "look," because they so often mis-state the structure and meaning of what they're requesting. This isn't meant as a dig at you. Rather, I'm pointing out that this issue really seems to be that Ada has a different "look and feel" than C++ or Smalltalk. Adding a "class" encapsulator and "object.method" notation certainly won't change that! Trying to write Ada code that conforms to a C++ view of syntax and semantics is as foolish as trying to write C++ code to look like Ada. To some extent, if you could just uproot notations from one language and plop them down in the other, there'd be no reason to have both languages. I feel that both C++ and Ada have real value. I feel it's good to have BOTH languages -- our understanding of the deeper issues is greatly enhanced by having more than one way to express them. Philosophy final exam: "Describe human thought. Compare and contrast with any other kind of thought." > Maybe I just don't understand the issues. I would appreciate any help > in making this clear. I hope you found this helpful. > Shawn M. Root Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 ` Samuel Mize @ 1999-05-20 0:00 ` David Botton 1999-05-20 0:00 ` Samuel Mize 1999-05-24 0:00 ` Hyman Rosen 1 sibling, 1 reply; 116+ messages in thread From: David Botton @ 1999-05-20 0:00 UTC (permalink / raw) > > Trying to write Ada code that conforms to a C++ view of syntax and > semantics is as foolish as trying to write C++ code to look like Ada. I don't think it is so foolish to write C++ code that looks like Ada code. IMHO Good C++ code should look very much like Ada. Clear separation between specs and body. Clear long object names and variables, documentation, etc. In fact even C++ standards have been working hard to add more Ada in to C++, for example packages (name spaces) David Botton Writing ADA for Ada is like C PLUS PLUS for C++. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 ` David Botton @ 1999-05-20 0:00 ` Samuel Mize 1999-05-20 0:00 ` David Botton 0 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-20 0:00 UTC (permalink / raw) David Botton <David@Botton.com> wrote: >> >> Trying to write Ada code that conforms to a C++ view of syntax and >> semantics is as foolish as trying to write C++ code to look like Ada. > > I don't think it is so foolish to write C++ code that looks like Ada > code. Well, I meant in both cases "writing code that conforms to the language X view of syntax and semantics." For perfect clarity, I should have repeated the entire phrase in the second parallel clause. I hope you'll agree that it would not be good C/C++ coding style to, for instance, use preprocessor macros to turn "BEGIN" and "END" into "{" and "}" so your C/C++ code would look more like Ada. Each language has a "view of syntax and semantics" that defines it, and you should work within its own view of itself, not try to force the view of other languages on it. > IMHO Good C++ code should look very much like Ada. Clear separation > between specs and body. Clear long object names and variables, > documentation, etc. You're saying that good C++ should look very much like GOOD Ada, in those ways that are language-independent. But it will still use C++ syntax and semantics. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 ` Samuel Mize @ 1999-05-20 0:00 ` David Botton 0 siblings, 0 replies; 116+ messages in thread From: David Botton @ 1999-05-20 0:00 UTC (permalink / raw) > I hope you'll > agree that it would not be good C/C++ coding style to, for instance, use > preprocessor macros to turn "BEGIN" and "END" into "{" and "}" so your > C/C++ code would look more like Ada. Actually I should give it a try. I should add a // after the "{" and "}" so I can do ( and of course define procedure as void, print_line as printf, and new_line as printf("\n") ): procedure main() begin -- main put("Hello World"); new_line; end main; Much better now :-) David Botton ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 ` Samuel Mize 1999-05-20 0:00 ` David Botton @ 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Robert Dewar ` (2 more replies) 1 sibling, 3 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-24 0:00 UTC (permalink / raw) Samuel Mize <smize@imagin.net> writes: > There are other OO design approaches that are harder to implement in > C++ than in Ada, because C++ strongly supports one specific view of > object-oriented technology. Could you give an example of this? I ask, because recently Richard D. Riehle made a similar type of claim, and then declined to post an example. I believe that many posters to this group are very proficient in Ada but not as proficient in C++, so they may be mistaken about what is difficult to do in C++. Posting an example allows proficient C++ users to examine the apparently difficult code and offer alternatives. (Note that I am not looking for arbitrary examples of where Ada is better than C++. I know that Ada is better, for example, in defining data storage layout that conforms to external specifications, while C++ is better in providing automatic generic instantiation.) ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Hyman Rosen @ 1999-05-24 0:00 ` Robert Dewar 1999-05-24 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Samuel Mize 1999-06-03 0:00 ` Matthew Heaney 2 siblings, 1 reply; 116+ messages in thread From: Robert Dewar @ 1999-05-24 0:00 UTC (permalink / raw) In article <t7lneeqlzf.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> wrote: > Could you give an example of this? I ask, because recently Richard > D. Riehle made a similar type of claim, and then declined to post an > example. I believe that many posters to this group are very proficient > in Ada but not as proficient in C++, so they may be mistaken about > what is difficult to do in C++. Posting an example allows proficient > C++ users to examine the apparently difficult code and offer > alternatives. Well obviously the case of extending an algebra that implements symmetrical binary operators is a case more easily handled in Ada than in C, I assume a specific example is not needed here? But presumably you are looking for different kinds of things? > (Note that I am not looking for arbitrary examples of where Ada is > better than C++. I know that Ada is better, for example, in defining > data storage layout that conforms to external specifications, while > C++ is better in providing automatic generic instantiation.) Actually these two examples are not at all comparable. The ability to declare data storage layout is a fundamental functionality feature. Automatic generic instantiation is a mechanism, which one may or may not like. You can't really say that C++ is better in this department if your viewpoint is that automatic generic instantiation is a risky feature! So it is better to find examples of fundamental functionality rather than mechanisms. Of course the discussion about OO features is entirely about mechanisms! --== Sent via Deja.com http://www.deja.com/ ==-- ---Share what you know. Learn what you don't.--- ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Robert Dewar @ 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Mike 1999-05-24 0:00 ` David Starner 0 siblings, 2 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-24 0:00 UTC (permalink / raw) Robert Dewar <robert_dewar@my-dejanews.com> writes: > Well obviously the case of extending an algebra that implements > symmetrical binary operators is a case more easily handled in > Ada than in C, I assume a specific example is not needed here? Actually, I would like a specific example - I don't understand "an algebra that implements symmetrical binary operators" or why it's easier in Ada. I'm not being difficult here - I really just don't understand the meaning of the quoted phrase, so a bit of actual code would go a long way to clarify things. > But presumably you are looking for different kinds of things? I posted the request in response to the claim that Ada allows certain object-oriented techniques that are more difficult to express in C++. I would like to see a bit of code demonstrating this, to determine to my own satisfaction whether it's really true, or whether the Ada poster doesn't know enough C++ to realize that it's easy there as well. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Hyman Rosen @ 1999-05-24 0:00 ` Mike 1999-05-25 0:00 ` Robert Dewar 1999-05-24 0:00 ` David Starner 1 sibling, 1 reply; 116+ messages in thread From: Mike @ 1999-05-24 0:00 UTC (permalink / raw) In article <t7g14mqe7b.fsf@calumny.jyacc.com>, Hyman says... > >Robert Dewar <robert_dewar@my-dejanews.com> writes: >> Well obviously the case of extending an algebra that implements >> symmetrical binary operators is a case more easily handled in >> Ada than in C, I assume a specific example is not needed here? > >Actually, I would like a specific example - Prof. Dewar is not adopt to giving examples. He likes to give theories, but not examples, that is why he is a prof. :) Mike ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Mike @ 1999-05-25 0:00 ` Robert Dewar 0 siblings, 0 replies; 116+ messages in thread From: Robert Dewar @ 1999-05-25 0:00 UTC (permalink / raw) In article <7icota$1fdh@drn.newsguy.com>, Mike <Mike@newsguy.com> wrote: > Prof. Dewar is not adopt to giving examples. He likes to give > theories, but not examples, that is why he is a prof. :) I often give examples where they are new and instructive. This is such a well known example, which has been beaten to death in previous threads, that it hardly seems worthwhile. Part of the trouble with CLA is that it tends to recycle old threads as new people join the discussion, but that can be quite time wasting! The issue with binary operators in tagged types is quite fundamental. I refer anyone interested in this issue to read the Ada 95 rationale, which addresses it. --== Sent via Deja.com http://www.deja.com/ ==-- ---Share what you know. Learn what you don't.--- ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Mike @ 1999-05-24 0:00 ` David Starner 1999-05-24 0:00 ` bob 1 sibling, 1 reply; 116+ messages in thread From: David Starner @ 1999-05-24 0:00 UTC (permalink / raw) Hyman Rosen wrote: > > Robert Dewar <robert_dewar@my-dejanews.com> writes: > > Well obviously the case of extending an algebra that implements > > symmetrical binary operators is a case more easily handled in > > Ada than in C, I assume a specific example is not needed here? > > Actually, I would like a specific example - I don't understand > "an algebra that implements symmetrical binary operators" or > why it's easier in Ada. I'm not being difficult here - I really > just don't understand the meaning of the quoted phrase, so a > bit of actual code would go a long way to clarify things. Think of vectors and the dot product. C++ forces you to view one vector as significant (a becomes "this" inside dot function, it's called a.dot(b)), even though in a dot b, a and b are equal significance - dot product is a symmetric function. Ada makes them of equal importnatce in the dot function body and call. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` David Starner @ 1999-05-24 0:00 ` bob 1999-05-24 0:00 ` David Starner 0 siblings, 1 reply; 116+ messages in thread From: bob @ 1999-05-24 0:00 UTC (permalink / raw) In article <3749E9EC.2842436A@aasaa.ofe.org>, David says... > >Think of vectors and the dot product. C++ forces you to view one vector >as significant (a becomes "this" inside dot function, it's called >a.dot(b)), even though in a dot b, a and b are equal significance - dot >product is a symmetric function. Ada makes them of equal importnatce in >the dot function body and call. Are sure you are not talking about Java (which does not have user defined operators) ? You have to do the above in Java 'a.dot(b)' but in C++, (unless '.' is one of those few things that are not allowed to be redefined), I can write 'a.b' just fine, why not? Bob ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` bob @ 1999-05-24 0:00 ` David Starner 1999-05-25 0:00 ` Ole-Hjalmar Kristensen 0 siblings, 1 reply; 116+ messages in thread From: David Starner @ 1999-05-24 0:00 UTC (permalink / raw) bob wrote: > > In article <3749E9EC.2842436A@aasaa.ofe.org>, David says... > > > > >Think of vectors and the dot product. C++ forces you to view one vector > >as significant (a becomes "this" inside dot function, it's called > >a.dot(b)), even though in a dot b, a and b are equal significance - dot > >product is a symmetric function. Ada makes them of equal importnatce in > >the dot function body and call. > > Are sure you are not talking about Java (which does not have user defined > operators) ? Yes. I was discussing a.dot(b) vs. dot(a,b), not user defined operators. > > You have to do the above in Java 'a.dot(b)' > > but in C++, (unless '.' is one of those few things that are not > allowed to be redefined), I can write 'a.b' just fine, why not? First, I don't believe . is allowed to be redefined. Second, "." is not the dot product dot (which I can't represent in ASCII.) Third, redefining "." is evil - "." in C++ is a synatic element, not a multiplicitave operator, and changing that is going to really confuse any reader of the code. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` David Starner @ 1999-05-25 0:00 ` Ole-Hjalmar Kristensen 1999-05-25 0:00 ` Florian Weimer 1999-05-25 0:00 ` Mark A Biggar 0 siblings, 2 replies; 116+ messages in thread From: Ole-Hjalmar Kristensen @ 1999-05-25 0:00 UTC (permalink / raw) David Starner <dstarner98@aasaa.ofe.org> writes: > bob wrote: > > > > In article <3749E9EC.2842436A@aasaa.ofe.org>, David says... > > > > > > > >Think of vectors and the dot product. C++ forces you to view one vector > > >as significant (a becomes "this" inside dot function, it's called > > >a.dot(b)), even though in a dot b, a and b are equal significance - dot > > >product is a symmetric function. Ada makes them of equal importnatce in > > >the dot function body and call. > > > > Are sure you are not talking about Java (which does not have user defined > > operators) ? > Yes. I was discussing a.dot(b) vs. dot(a,b), not user defined operators. > > What makes you think you cannot implement dot(a,b) in C++? <stuff deleted> -- E pluribus Unix ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Ole-Hjalmar Kristensen @ 1999-05-25 0:00 ` Florian Weimer 1999-05-25 0:00 ` Mark A Biggar 1 sibling, 0 replies; 116+ messages in thread From: Florian Weimer @ 1999-05-25 0:00 UTC (permalink / raw) Ole-Hjalmar Kristensen <ohk@clustra.com> writes: > What makes you think you cannot implement dot(a,b) in C++? In C++, you won't get late binding (aka dynamic dispatching, aka virtual methods) this way. In Ada, you will. You could provide some kind of wrapper function to obtain the same effect in C++, but I think the Ada solution to this particular problem (i.e. no need for a wrapper function) is clearly more elegant. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Ole-Hjalmar Kristensen 1999-05-25 0:00 ` Florian Weimer @ 1999-05-25 0:00 ` Mark A Biggar 1999-05-25 0:00 ` Hyman Rosen 1 sibling, 1 reply; 116+ messages in thread From: Mark A Biggar @ 1999-05-25 0:00 UTC (permalink / raw) Ole-Hjalmar Kristensen wrote: > > David Starner <dstarner98@aasaa.ofe.org> writes: > > > bob wrote: > > > > > > In article <3749E9EC.2842436A@aasaa.ofe.org>, David says... > > > > > > > > > > >Think of vectors and the dot product. C++ forces you to view one vector > > > >as significant (a becomes "this" inside dot function, it's called > > > >a.dot(b)), even though in a dot b, a and b are equal significance - dot > > > >product is a symmetric function. Ada makes them of equal importnatce in > > > >the dot function body and call. > > > > > > Are sure you are not talking about Java (which does not have user defined > > > operators) ? > > Yes. I was discussing a.dot(b) vs. dot(a,b), not user defined operators. > > > > > What makes you think you cannot implement dot(a,b) in C++? You can, but there are some problems with doing that. 1) It's not really part of the class as it has to be defined as an external "friend" function. 2) It therefore CANNOT be made virtual so you can't dispatch on it. 3) This also greatly complicates its use in generic (template) algorithms. None of those problems exist in Ada. -- Mark Biggar mark.a.biggar@lmco.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Mark A Biggar @ 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Samuel Mize ` (3 more replies) 0 siblings, 4 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-25 0:00 UTC (permalink / raw) Mark A Biggar <mark.a.biggar@lmco.com> writes: > 1) It's not really part of the class as it has to be defined as > an external "friend" function. Friend functions and classes constitute parts of an interface. Some people would like to criticize C++ both for "requiring that everything be inside a class" and then again for using friends "which are not part of the class". They merely, or willfully, misunderstand the C++ model. > 2) It therefore CANNOT be made virtual so you can't dispatch on it. So you mean in Ada, I can write a dot(a,b) which will dispatch on either a or b? I wasn't aware that this was the case. I actually think that this is in fact *not* the case, in which case I have no trouble writing a dispatching version in C++ either - just have dot(a,b) call a.dot(b). In both Ada and C++, the apparent external symmetry will then hide the internal asymmetry. > 3) This also greatly complicates its use in generic (template) algorithms. > None of those problems exist in Ada. Once again, I will ask for an example demonstrating this, where something is more complicated to use in C++ generics than in Ada. This will make you the fourth person I have asked for this type of example, the others being Richard D. Riehle, Samuel Mize, and Robert Dewar. None of the others have chosen to post such an example. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen @ 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Richard D Riehle ` (2 subsequent siblings) 3 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-25 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > So you mean in Ada, I can write a dot(a,b) which will dispatch on > either a or b? Yes. Either can be controlling. If both are controlling, they both have to be of the same type (the same class in C++ terms). [uncompiled example] type A_Type is tagged with null record; -- All of these dispatch on A if it's a dispatching call procedure Operation_1 (A: A_Type; I: Integer); procedure Operation_2 (I: Integer; A: A_Type); procedure Operation_3 (A: A_Type; B: A_Type'Class); -- This dispatches on both parameters, so they have to match -- at run-time procedure Operation_4 (A: A_Type; B: B_Type); > Once again, I will ask for an example demonstrating this, where > something is more complicated to use in C++ generics than in Ada. > This will make you the fourth person I have asked for this type > of example, the others being Richard D. Riehle, Samuel Mize, and > Robert Dewar. None of the others have chosen to post such an > example. Not instantly. I did address this to the best of my ability in another message, just today. I'll grant that I don't have a code example handy, and I'll grant that I was repeating "conventional wisdom" from the group. Did you intend that paragraph to sound contentious? To my ear, at least, it has rather a "you're all liars, I'm naming names" sound to it -- I hope that isn't what you meant. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Samuel Mize @ 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Richard D Riehle ` (4 more replies) 0 siblings, 5 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-25 0:00 UTC (permalink / raw) Samuel Mize <smize@imagin.net> writes: > -- This dispatches on both parameters, so they have to match > -- at run-time > procedure Operation_4 (A: A_Type; B: B_Type); (Do you mean B: A_Type ?) Thanks, this is the kind of example I meant! This is something that C++ can't do by itself. When you say "match at runtime" do you mean that their dynamic types must be the same? Does the code raise an exception if they happen not to match? If I were to code this in C++, I could do the following: void Operation_4(A_Type &A, A_Type &B) { if (typeid(A) != typeid(B)) throw "Mismatched types!"; A.Operation_4(B); } The method Operation_4 of all subclasses of A_Type would have to be written to take a paremeter of type A_Type, so it's not nearly as nice as Ada, where I assume that this does not have to be the case. > Did you intend that paragraph to sound contentious? To my ear, > at least, it has rather a "you're all liars, I'm naming names" > sound to it -- I hope that isn't what you meant. I wanted it to sound somewhat contentious. The named people each claimed in a posting that there were object-oriented techniques that were harder, or less elegant, in C++ than in Ada. I asked for examples with the thought that perhaps the posters didn't know C++ as well as they knew Ada, and were therefore perhaps mistaken. There were responses, but no code, so I got a little testy. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen @ 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Hyman Rosen ` (3 more replies) 1999-05-25 0:00 ` Brian Rogoff ` (3 subsequent siblings) 4 siblings, 4 replies; 116+ messages in thread From: Richard D Riehle @ 1999-05-25 0:00 UTC (permalink / raw) In article <t7675gswiv.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> wrote: >I wanted it to sound somewhat contentious. The named people each >claimed in a posting that there were object-oriented techniques >that were harder, or less elegant, in C++ than in Ada. I asked >for examples with the thought that perhaps the posters didn't know >C++ as well as they knew Ada, and were therefore perhaps mistaken. >There were responses, but no code, so I got a little testy. OK. There are hundreds of source code examples one could choose. I promised myself not to get into this any further, but it just isn't to be. I am going to give just this one example illustrating array management using Ada with the suggestion that Mr. Rosen post some corresponding code in C++. My apologies to those of you in the Ada community who prefer to avoid these bladder-purging contests. In C++ every array begins with an index of zero. This makes array algorithms slightly more awkward than Ada. Ada does not assume that everything in the world begins with zero. In C++, this often results in "off by one" errors, all too easy to create, all too difficult to debug in large programs. Of course, no intelligent programmer would make this mistake. ;) Also, multiple dimension arrays in Ada may be declared as actual multiple dimension arrays as well as arrays of arrays. I assume you know C++ well, so will not bother to code each example in C++ except where necessary. Here are some Ada examples that are useful. Example One: type Float_32 is digits 6; -- declare 32 bit float; for Float_32'Size use 32; -- force size to 32 bits type Index is range -42..42; -- a constrained array type type Life_Universe_And_Everything is array(Index) of Float_32; Babel_Fish : Life_The_Universe_And_Everything; Now we might want to traverse this array from beginning to end. Ada makes this quite easy. Consider, for I in Babel_Fish'Range loop -- some computation end loop; That is readable Ada. Since you are the C++ expert, we leave it to you to supply a corresponding loop in C++, one that processes an array with a negative index. Example 2: Ada will permit us to declare an unconstrained array in which the index may be of any discrete type. The index does not even have to be an integer. We will, however, use an integer type type in this example. type My_Index is range - 2**12..2**12-1: -- (-4096 .. 4095); type FourKarray is array(My_Index <>) of Float_32; The array is an unconstrained array. Before we may use it, it must be constrained. We may also call a function or procedure with an unconstained array and generalize the code quite nicely. The_Array : FourKarray(-3000..2000); procedure Process(Data : in out FourKarray) is begin for I in F'Range loop -- actions on array, F; end loop; end Process; We might call Process with X, Process(Data => The_Array); -- associate formal with actual Once again, you might supply C++ code for this algorithm and the corresponding procedure call. Example 3: As mentioned earlier, Ada permits many techniques for declaring and traversing multiple dimensional arrays. Here is an example that you might find interesting. type Month is (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sept, Oct, Nov, Dec); type Day is range 1..31; type Day_Of_Month is array(Month, Day) of Boolean; Now we want to traverse the array with Month as the major index of our loop. for I in Day_Of_Month'Range(1) loop for J in Day_Of_Month'Range(2) loop -- Do something to element of matrix if some-condition then Day_Of_Month(I, J) := True; end if; end loop; end loop; Notice that the enumerated type is an ordered set, unlike C++. Also, there is no need to do any arithmetic on the enumerated type. In the example shown, we are permitted to identify which dimension of the array is being processed by putting it in parentheses. Therefore, 'Range(2) refers to the second dimension. This is handy if I decide to do it differently. Consider, for I in Day_Of_Month'Range(2) loop for J in Day_Of_Month'Range(1) loop -- Do something to element of matrix if some-condition then Day_Of_Month(I, J) := True; end if; end loop; end loop; where we change the major and minor dimensions through a simple alteration of the 'Range(X) attribute. Once again, you are challenged to provide corresponding code in C++. I could many more more examples of array processing in Ada that are simple, straightforward and easy to code. One more important point; the index to the array is a constant and only lives as long as the scope of the array. In the current C++ standard, the index also goes out of scope, but this was not always the case. Some C++ compilers do not yet apply the current standard, and some permit the older code to still compile in the interest portability -- but at the expense of reliability. More important, in C++ one can code a loop such as, for (i = 0; i < 10; i++) { // some code here i = 10; } which would be illegal in Ada for safey reasons. In general, array and matrix processing in Ada is so much superior to C++ that it makes me wonder why anyone would even raise a question about it. It is not unknown, in C++ programs, to have defects that result from simple programming errors. For example, has anyone ever coded i++ when they intended ++i? Will it make a difference in the behavior of the program? Will the compiler even bother to give you a warning? On the other hand, we could find some illustrations where C++ does certain things better than Ada. That problme is left as an exercise to the student. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Richard D Riehle @ 1999-05-25 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Ray Blaak [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <t7emjmmx8w.fsf@calumny.jyacc.com> ` (2 subsequent siblings) 3 siblings, 1 reply; 116+ messages in thread From: Hyman Rosen @ 1999-05-25 0:00 UTC (permalink / raw) Richard D Riehle <laoXhai@ix.netcom.com> writes: > In article <t7675gswiv.fsf@calumny.jyacc.com>, > Hyman Rosen <hymie@prolifics.com> wrote: > >I wanted it to sound somewhat contentious. The named people each > >claimed in a posting that there were object-oriented techniques > >that were harder, or less elegant, in C++ than in Ada. ...and follows up with code demonstrating the superiority of Ada array handling over the C++ version. I agree completely. Native Ada array handling beats the pants off of native C++ array handling. Any equivalent I could produce in C++ would be longer, require custom classes, and be nowhere near as nice. Array indexing, however, does not normally fall under the heading of object-oriented techniques. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen @ 1999-05-26 0:00 ` Ray Blaak 1999-05-26 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Richard D Riehle 0 siblings, 2 replies; 116+ messages in thread From: Ray Blaak @ 1999-05-26 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > ...and follows up with code demonstrating the superiority of Ada > array handling over the C++ version. [...] > Array indexing, however, does not normally fall under the heading > of object-oriented techniques. Well, here is an OO example showing difficulties with the C++ model as compared to Ada. It is about a generic/template vector class with binary operators involving scalars. In Ada, due to its method(obj,parm) notation, things are declared in a straight forward way. In C++, friend procedures are required, which is no suprise. The problem with C++, however, is that friend functions cannot be implicitly instantiated when the vector class is instantiated. Ada: generic type ScalarType is (<>); -- Is this right? My Ada is rusty. package Vector is type T is private; function Create(size : Natural) : T; function "*" (vector : in T; scalar : in ScalarType) : T; function "*" (scalar : in ScalarType; vector : in T) : T; private -- whatever end; declare package IntVector is new Vector(Integer); use type IntVector; package FloatVector is new Vector (Float); use type FloatVector; I : IntVector.T := IntVector.Create(3); F : FloatVector.T := FloatVector.Create(3); begin I := I*2; I := 2*I; F := F*2; F := 2*F; end; C++: template <typename ScalarType> class Vector { public: Vector (int size) { /* whatever */ }; ~Vector() {}; Vector operator* (ScalarType scalar) {return Vector(0); /* whatever */}; friend Vector operator* (ScalarType scalar, Vector & V); }; Vector<int> operator* (int scalar, Vector<int> & V) { return V * scalar; } // later: Vector<int> I(3); I = I * 2; I = 2 * I; Vector<float> F(3); F = F * 2; F = 2 * F; In this example, things won't link because I "forgot" to declare the Vector<float> friend function. Not a big deal, since I can just do it. However, it is tedious that I don't get what I need as soon as Vector<float> is instantiated. I could make a mistake in defining it. If one could have template namespaces, then maybe the class and friend function could be defined together, but then one would have to switch to the instantiated namespace (analogous to the "use type" in the Ada above, I suppose). The point is the C++ is a little more clumsy in this regard. If anyone has a way to do the C++ example cleanly, I would be most interested, since I currently use C++ in my projects. In particular, I was playing with defining the friend function as: template<typename ScalarType> Vector<ScalarType> operator*(...) {...} but couldn't get it to work. -- Cheers, The Rhythm is around me, The Rhythm has control. Ray Blaak The Rhythm is inside me, blaak@infomatch.com The Rhythm has my soul. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Ray Blaak @ 1999-05-26 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Richard D Riehle 1 sibling, 0 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-26 0:00 UTC (permalink / raw) Ray Blaak <blaak@infomatch.com> writes: > Well, here is an OO example showing difficulties with the C++ model > as compared to Ada. > > Ada: > > generic > type ScalarType is (<>); -- Is this right? My Ada is rusty. > package Vector is > type T is private; > > function Create(size : Natural) : T; > > function "*" (vector : in T; scalar : in ScalarType) : T; > function "*" (scalar : in ScalarType; vector : in T) : T; > private > -- whatever > end; > > declare > package IntVector is new Vector(Integer); > use type IntVector; > package FloatVector is new Vector (Float); > use type FloatVector; > > I : IntVector.T := IntVector.Create(3); > F : FloatVector.T := FloatVector.Create(3); > begin > I := I*2; > I := 2*I; > F := F*2; > F := 2*F; > end; OK, here's the C++, which compiles without error with EGCS: template <typename ScalarType> struct Vector { explicit Vector(int n); Vector operator *(ScalarType scalar) const; friend Vector operator *(ScalarType scalar, const Vector &v) { return v * scalar; } }; int main() { Vector<float> f(3); Vector<int> i(2); f * 2; 2 * f; i * 7; 7 * i; } > In this example, things won't link because I "forgot" to declare the > Vector<float> friend function. By writing the function inside the class, I've wriiten it once for all types with which Vector is instantiated. > The point is the C++ is a little more clumsy in this regard. If anyone has a > way to do the C++ example cleanly, I would be most interested And that was pretty much my point. People who know one language better than another will often think that the other language is incapable or clumsy at certain things. Often, this is not the case. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Ray Blaak 1999-05-26 0:00 ` Hyman Rosen @ 1999-05-26 0:00 ` Richard D Riehle 1999-05-26 0:00 ` Hyman Rosen 1 sibling, 1 reply; 116+ messages in thread From: Richard D Riehle @ 1999-05-26 0:00 UTC (permalink / raw) In response to my example showing array handling in Ada versus C++, >Hyman Rosen <hymie@prolifics.com> writes: >> ...and follows up with code demonstrating the superiority of Ada >> array handling over the C++ version. >[...] >> Array indexing, however, does not normally fall under the heading >> of object-oriented techniques. Yes, I suppose that is true. Array management and implementation details of other container classes is more the province of programming than object-oriented programming. However, someone once said, "The Devil is in the details." Since part of this discussion began as a question regarding the C++ versus the Ada generic in OOP, perhaps it is instructive to note that the array example is not completely unrelated to the original quest, especially when one considers the details. Nevertheless, the above point will not satisfy those with a need for more OO specific examples. So I will take some time and return to my software greenhouse to grow some additional examples, especially since my email has explicitly encouraged me to continue the "bladder purging" contest. The examples will not appear instantaneously since I do have to devote a small portion of my workday to actual work. One idea that occurred to me driving to work this morning was a nice feature of Ada that allows me to overload a function based on return type and use that return type as a controlling result for dispatching. Also, the ability to create functions that return a classwide type. The value of those features could be lost on someone not familiar with Ada, but they serve as powerful design mechanisms. For example, in the same scope and visibility type T is tagged ... function Get(F : some-file) return T; function Get(F : access some-file) return T; function Get(F : some-file) return T'Class; type B is new T with ... function Get(F : some-file) return B; function Get(F : access some-file) return B; where the two type specific Get's are dispatching operations and the return type resolves the overloading. This is not possible in C++ and it limits certain design decisions. There are dozens of these kinds of examples. It is interesting that this example also extends itself to the design of templates and makes Ada a little more flexible. One of the original contentions was that, although the C++ model of class <=> type <=> module appears to be simpler on the surface, as one begins to design large scale software, that model becomes something of a straightjacket. It utltimately requires friend functions and other encapsulation-breaking features (such as the new "mutable" reserved word) to get around the restrictions imposed by such a small model of object-oriented programming. On the positive side, this same model has been used by Eiffel more successfully than by C++. This is probably because Eiffel did not begin with the need to counter side-effects inherited from C. In the new ISO C++ standard, many of those side-effects have been eliminated by proscribing some of the more dangerous features of C. However, Java, C++ and Eiffel all fail to explicitly separate the contract from the implementation. Separation of the contract from the implementation, while an option in C++, is not always desirable for technical reasons. This separation of contract from implementation is a far more important feature for good object-oriented programming than making the class and type and module the same unit. I will try to create some coded examples in the coming week. I hope others will also contribute to this thread. Even though the comparison of languages is often considered fruitless, I am beginning to believe it is important. Why? More and more of our DoD clients are making the mistake of choosing C++ instead of Ada for critical software. I think it is important that such decisions be made on the basis of good information. When the two languages are examined in depth, I have no doubt that an informed management would realize the benefits of Ada over C++. Sadly, too many of these decisions are being made on the basis of what seems to be rather than what really is. Richard Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Richard D Riehle @ 1999-05-26 0:00 ` Hyman Rosen 1999-05-27 0:00 ` Richard D Riehle ` (2 more replies) 0 siblings, 3 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-26 0:00 UTC (permalink / raw) Richard D Riehle <laoXhai@ix.netcom.com> writes: > For example, in the same scope and visibility > type T is tagged ... > function Get(F : some-file) return T; > function Get(F : access some-file) return T; > function Get(F : some-file) return T'Class; > type B is new T with ... > function Get(F : some-file) return B; > function Get(F : access some-file) return B; Overloading by return type and having that control dispatching looks like a good example of something that you can't do in C++. So is the concept of class-wide type itself - there's no equivalent in C++ for Ada's T'Class type. From a little fooling around with your code above and gnat, and the Rationale, it looks like the compiler has to examine the code that attempts to initialize a T'Class variable and allocate the maximum space for it that that code would require. C++ doesn't do any of that - C++ coders would be using dynamic allocation and pointers or references to pass around arbitray subclasses. Interesting. > One of the original contentions was that, although the C++ model of > class <=> type <=> module > appears to be simpler on the surface, as one begins to design large > scale software, that model becomes something of a straightjacket. It > utltimately requires friend functions and other encapsulation-breaking > features (such as the new "mutable" reserved word) to get around the > restrictions imposed by such a small model of object-oriented > programming. It is a fallacy that friend functions break encapsulation. Friendship is granted explicitly by a class. These friends are part of the encapsulation. Mutable has nothing at all to do with this - mutable members of an object may be modified even when the object is declared to be 'const'. The intent is to provide a difference between logical constness and physical constness. For example, one would expect that the characters of a const string would never change, but there could be an internal reference count that needs adjustment. That count would be declared mutable. For completeness sake, class member templates *can* be used to break encapsulation. The C++ philosophy is to protect encapsulation against Murphy but not Machiavelli. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Hyman Rosen @ 1999-05-27 0:00 ` Richard D Riehle 1999-06-05 0:00 ` Matthew Heaney 1999-05-28 0:00 ` Laurent Guerby 1999-06-05 0:00 ` Matthew Heaney 2 siblings, 1 reply; 116+ messages in thread From: Richard D Riehle @ 1999-05-27 0:00 UTC (permalink / raw) In article <t7k8tvqyjr.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> wrote: >Richard D Riehle <laoXhai@ix.netcom.com> writes: >> For example, in the same scope and visibility >> type T is tagged ... >> function Get(F : some-file) return T; >> function Get(F : access some-file) return T; >> function Get(F : some-file) return T'Class; >> type B is new T with ... >> function Get(F : some-file) return B; >> function Get(F : access some-file) return B; > >Overloading by return type and having that control dispatching looks >like a good example of something that you can't do in C++. So is the >concept of class-wide type itself - there's no equivalent in C++ for >Ada's T'Class type. From a little fooling around with your code above >and gnat, and the Rationale, it looks like the compiler has to examine >the code that attempts to initialize a T'Class variable and allocate >the maximum space for it that that code would require. C++ doesn't do >any of that - C++ coders would be using dynamic allocation and pointers >or references to pass around arbitray subclasses. Interesting. In actual Ada OOP, especially when using Stream_IO for storage of heterogenuous types, it is typical to use access (pointer) types also. One reason I used the illustration with access parameters is to accomodate that practice. Now for the bad news. Ada access parameters allow the programmer to violate the encapsulation too. Although the access parameter itself is regarded as an in parameter in Ada, a programmer may dereference data being referenced, if there is visibility to the data. In this regard, I think C++ is a little stronger because of the option of const functions and const parameters. My preference for a future addition to the Ada standard would be some kind of constant function such as, constant function F (A : access some-type) return T; or, closer to C++, function F (A : constant access some-time) return T; which would disallow any monkey business with the function. In fact, this would correspond to the notion of a query with no possible ] side-effects (much like the protected type function) and satisfy Bertrand Meyer's insistence that queries should only query and modifiers should only modify. This is one feature of Ada, for object-oriented programming where I think C++ is a little stronger. >It is a fallacy that friend functions break encapsulation. Friendship >is granted explicitly by a class. These friends are part of the >encapsulation. Friends are "part of the encapsulation", but also seem, to me, to be an awkward feature included to compensate for problems associated with the class <=> type <=> module model. Without this kind of model, the notion of friends would be unnecessary. >Mutable has nothing at all to do with this - mutable >members of an object may be modified even when the object is declared >to be 'const'. The intent is to provide a difference between logical >constness and physical constness. For example, one would expect that >the characters of a const string would never change, but there could >be an internal reference count that needs adjustment. That count would >be declared mutable. I understand that mutable is a feature for reversing const'ness. We have in Ada the notion of a general access constant that satisfies the situation you mention, if I understand your explanation. It just seems, once again, that this is an add-on to compensate for a language weakness rather than a coherent part of the overall design. >For completeness sake, class member templates *can* be used to break >encapsulation. The C++ philosophy is to protect encapsulation against >Murphy but not Machiavelli. This is a key difference between Ada and C++. Ada, the language, is designed to maximize the number of errors that can be caught during compilation, as early in the process as possible. This is one reason for requiring that ancestral library units be correctly compiled before one can compile a dependent unit. It is one reason why access types (pointers) are so strictly controlled, and it is also why we have, in Ada, a strong separation between the notions of scope and visibility. The philosophies of the two language designs are different. As you noted earlier regarding templates, if it compiles in C++, it is OK, but there may be problems lurking in the code. In Ada, the goal is to ensure that a compiled template (generic) correspond completely to the associated signatures of generic formal parameters. This is one reason Ada generic formal package parameters seem, at first, to be more bizzare than those in C++. We are trying to put both Murphy and Machiavelli out of business. Too ambitious. Probably. But that is the goal, and one reason why Ada is designed as it is. I have enjoyed our little discussions. Thanks for your participation. It is now essential I return to doing some real programming even though this has been fun. Thanks, Hyman, Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Richard D Riehle @ 1999-06-05 0:00 ` Matthew Heaney 1999-06-07 0:00 ` Hyman Rosen 0 siblings, 1 reply; 116+ messages in thread From: Matthew Heaney @ 1999-06-05 0:00 UTC (permalink / raw) Richard D Riehle <laoXhai@ix.netcom.com> writes: > Now for the bad news. Ada access parameters allow the programmer > to violate the encapsulation too. Although the access parameter > itself is regarded as an in parameter in Ada, No. An access parameter is an in out param, that automatically dereferences a pointer. An access parameter is used to implement by-reference abstractions: type T (<>) is tagged limited private; procedure Op (O : access T); Singletons that are instances of a type are written this way: package Mazes.Games is type Maze_Type (<>) is limited private; type Maze_Access is access all Maze_Type; function Maze return Maze_Access; function Get_Room (Maze : access Maze_Type; Number : in Room_Number) return Room_Access; ... end Mazes.Games; So a client would just say: Room : constant Room_Access := Get_Room (Maze, 2); ^^^^ Access parameters give Ada reference-semantics, without the syntactic overhead (having to say .all everywhere). There are many examples of this idiom in the ACM patterns archive: <http://www.acm.org/archives/patterns.html> > a programmer may dereference data being referenced, if there is > visibility to the data. Yes, but in the current version of Ada, an access parameter is really an in out parameter. You are correct in pointing out that there are times when an operation doesn't need to modify the state of the object, even though it takes an access parameter. But I don't buy the argument that this makes all kinds of abuse possible. A client can only manipulate an abstraction using the (primitive) operations provided. And the writer of an abstraction has visibility to the implementation anyway. He's not going to suddenly go berserk, arbitrarily changing state, just because one of the operations happens to take an access param instead of an access constant param. > In this regard, I think C++ is a little stronger because of the > option of const functions and const parameters. My preference for a > future addition to the Ada standard would be some kind of constant > function such as, > > constant function F (A : access some-type) return T; > > or, closer to C++, > > function F (A : constant access some-time) return T; > > which would disallow any monkey business with the function. The more likely scenario will be: procedure Op (O : access constant T); function Op (O : access constant T) return Item; This was considered for Ada95 but didn't make the cut, because the language designers were trying to keep the number of language changes small. In this respect, C++ is superior to Ada95, but not for the reasons you argue. > In fact, this would correspond to the notion of a query with no > possible side-effects (much like the protected type function) and > satisfy Bertrand Meyer's insistence that queries should only query > and modifiers should only modify. Then I disagree with Bertrand (what else is new). From a specification point of view, a selector might not be state-changing, but there may be very good reasons to make an internal state-change. For example, one might wish to record how many times a certain function was invoked. "Casting away const" is a useful, and necessary, feature. > This is one feature of Ada, for object-oriented programming where > I think C++ is a little stronger. The problem with Ada is that it doesn't separate interface from implementation enough. The parameter modes that appear in a spec apply to the body too - but why? For example, there's no easy way to write the function I mentioned above: function Get_Item (O : in T) return Item_Type; Now how am I supposed to record that Get_Item got invoked? T has mode in, not in out, so I can't easily change O's state. Suppose I had in out function params: function Get_Item (O : in out T) return Item_Type; This would solve my problem, but it's still advertising more than I really wish to advertise. Why does the client care that O is in out? (He doesn't.) I only needed to state that in the spec, because it's what I need to do in the body. > >It is a fallacy that friend functions break encapsulation. Friendship > >is granted explicitly by a class. These friends are part of the > >encapsulation. > > Friends are "part of the encapsulation", but also seem, to me, to be > an awkward feature included to compensate for problems associated > with the class <=> type <=> module model. Without this kind > of model, the notion of friends would be unnecessary. Yes. You need friend because the type and mode were coupled. In Ada, visibility is controlled by the module feature, which is separate from the type feature, which means a friend feature isn't necessary. The "bad" thing about the friend construct is not that it violates information hiding; after all, child packages and co-declarations allow you to "violate" information hiding too. The issue is that you can't extend visibility from one abstraction to another without paying a compilation penalty. > >Mutable has nothing at all to do with this - mutable > >members of an object may be modified even when the object is declared > >to be 'const'. The intent is to provide a difference between logical > >constness and physical constness. For example, one would expect that > >the characters of a const string would never change, but there could > >be an internal reference count that needs adjustment. That count would > >be declared mutable. > > I understand that mutable is a feature for reversing const'ness. We > have in Ada the notion of a general access constant that satisfies > the situation you mention, if I understand your explanation. It just > seems, once again, that this is an add-on to compensate for a language > weakness rather than a coherent part of the overall design. Don't agree. This is a feature we don't have in Ada, and it is sorely missed. What we have to do now, in order to create a physical state-change in an object during an operation that is logically constant is: 1) make sure the type is a by-reference type, per RM95 6.2 (4) 2) take its address, per RM95 13.3 (16) 3) convert the address to an access-to-variable, per RM95 13.7.2 This is a royal pain in the ass. Worse, by having to go through an intermediate Address, we throw all type-checking out the window, which makes errors all the more likely. In effect, it reduces to a C program. Thankfully, gnat has 'Unrestricted_Access, which preserves all type checking, but this feature in non-portable. An example is the implementation of function Random: function Random (G : in Generator) return Uniformly_Distributed; See the files (especially the Implementation Note) a-nudira.ad? a-nuflra.ad? in the gnat sources for an example. There are many example of using Address_To_Access_Conversions in the ACM patterns archive, to get around these limitations in the language. <http:www.acm.org/archives/patterns.html> > >For completeness sake, class member templates *can* be used to break > >encapsulation. The C++ philosophy is to protect encapsulation against > >Murphy but not Machiavelli. The same is true in Ada95, via the child mechanism. You need a way to efficiently extend an abstraction, and this often requires extending visibility to the implementation. Both languages have satisfied the need, but by using different mechanisms. The benefit of the Ada way is that there is no compilation penalty. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-05 0:00 ` Matthew Heaney @ 1999-06-07 0:00 ` Hyman Rosen 0 siblings, 0 replies; 116+ messages in thread From: Hyman Rosen @ 1999-06-07 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > The "bad" thing about the friend construct is not that it violates > information hiding; after all, child packages and co-declarations allow > you to "violate" information hiding too. The issue is that you can't > extend visibility from one abstraction to another without paying a > compilation penalty. And you mention compilation penalty again later. What do you mean? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Hyman Rosen 1999-05-27 0:00 ` Richard D Riehle @ 1999-05-28 0:00 ` Laurent Guerby 1999-06-05 0:00 ` Matthew Heaney 2 siblings, 0 replies; 116+ messages in thread From: Laurent Guerby @ 1999-05-28 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > [...] > From a little fooling around with your code above > and gnat, and the Rationale, it looks like the compiler has to examine > the code that attempts to initialize a T'Class variable and allocate > the maximum space for it that that code would require. C++ doesn't do > any of that - C++ coders would be using dynamic allocation and pointers > or references to pass around arbitray subclasses. Interesting. [...] I think most Ada implementation use a secondary stack where such dynamix sized beasts are built, there's no need for "maximum space" allocation. Note that this feature of Ada is not linked to OO, the same mechanism is in place for function returning dynamically sized arrays. Of course the cost of this is spurious copying if the compiler isn't very clever. --LG ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Hyman Rosen 1999-05-27 0:00 ` Richard D Riehle 1999-05-28 0:00 ` Laurent Guerby @ 1999-06-05 0:00 ` Matthew Heaney 1999-06-07 0:00 ` Hyman Rosen 2 siblings, 1 reply; 116+ messages in thread From: Matthew Heaney @ 1999-06-05 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > From a little fooling around with your code above and gnat, and the > Rationale, it looks like the compiler has to examine the code that > attempts to initialize a T'Class variable and allocate the maximum > space for it that that code would require. No. The compiler has no way of knowing at compile-time how much space to allocate on the stack for the return value of the function. The size is determined at run-time. This is how factory methods work: procedure Print (Q : in Queue'Class) is Iter : Iterator'Class := Get_Iter (Q); -- -- Iter goes on the stack (not the heap), and its size is -- determined at run-time. begin ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-05 0:00 ` Matthew Heaney @ 1999-06-07 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Matthew Heaney 1999-06-08 0:00 ` Robert Dewar 0 siblings, 2 replies; 116+ messages in thread From: Hyman Rosen @ 1999-06-07 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > No. The compiler has no way of knowing at compile-time how much space > to allocate on the stack for the return value of the function. The size > is determined at run-time. From a little further fooling around, followed by a trip to the Ada RM, I see that objects of class-wide type can not be record components, which I guess makes sense, but it doesn't seem very orthogonal to me. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-07 0:00 ` Hyman Rosen @ 1999-06-08 0:00 ` Matthew Heaney 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Robert Dewar 1 sibling, 1 reply; 116+ messages in thread From: Matthew Heaney @ 1999-06-08 0:00 UTC (permalink / raw) On 07 Jun 1999 15:26:52 -0400, Hyman Rosen <hymie@prolifics.com> wrote: > Matthew Heaney <matthew_heaney@acm.org> writes: > > No. The compiler has no way of knowing at compile-time how much space > > to allocate on the stack for the return value of the function. The size > > is determined at run-time. > > From a little further fooling around, followed by a trip to the Ada RM, > I see that objects of class-wide type can not be record components, which > I guess makes sense, but it doesn't seem very orthogonal to me. I'm not sure what you mean by "doesn't seem very orthogal," but there are pragmatic reasons for not allowing a class-wide type as a record component. Just as the record decl type RT is record S : String; end record; is illegal, so is the decl type RT is record O : T'Class; end record; However, the declaration declare S : String := Func_Return_String; begin is perfectly legal, and so is the declaration declare O : T'Class := Func_Return_T_Tic_Class; begin In neither case is heap required. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Matthew Heaney @ 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Samuel Mize 0 siblings, 1 reply; 116+ messages in thread From: Hyman Rosen @ 1999-06-08 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > On 07 Jun 1999 15:26:52 -0400, Hyman Rosen <hymie@prolifics.com> wrote: > However, the declaration > declare > S : String := Func_Return_String; > begin > is perfectly legal, and so is the declaration > declare > O : T'Class := Func_Return_T_Tic_Class; > begin > In neither case is heap required. And despite that, you said before that the size of O is determined at run-time, not at compile-time. Also, I looked at some of the code generated by GNAT, and saw references to a secondary_stack_allocate (or something like that) function. So the storage for S and O is allocated somewhere, but it's on the stack? Is this something like alloca? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Hyman Rosen @ 1999-06-08 0:00 ` Samuel Mize 1999-06-08 0:00 ` Hyman Rosen 0 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-06-08 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > Matthew Heaney <matthew_heaney@acm.org> writes: ... >> declare >> O : T'Class := Func_Return_T_Tic_Class; >> begin >> In neither case is heap required. > > And despite that, you said before that the size of O is determined > at run-time, not at compile-time. Also, I looked at some of the code > generated by GNAT, and saw references to a secondary_stack_allocate > (or something like that) function. So the storage for S and O is > allocated somewhere, but it's on the stack? Is this something like > alloca? I infer from the name "Func_Return_T_Tic_Class" that this function returns a value of T'Class. It may be of type T, or of a type derived from T. O is allocated on stack, just like any other declare-block variable. (A function/procedure local variable would be just the same.) O will receive that value, and is of the specific type returned, for the duration of the declare block. Next time this block is executed, if Func's return is a different type, O will be of that specific type. O's size is determined at run-time, when it finds out exactly what type of object it has to hold. I should say, of course, that O is allocated on stack on typical architectures, by typical compilers. There is no concept of "stack" and "heap" required by the language, although Ada IS designed to give you control over heap usage on machines where that concept makes sense (as opposed, IIRC and e.g., to Lisp machines). Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Samuel Mize @ 1999-06-08 0:00 ` Hyman Rosen 0 siblings, 0 replies; 116+ messages in thread From: Hyman Rosen @ 1999-06-08 0:00 UTC (permalink / raw) Samuel Mize <smize@imagin.net> writes: > I should say, of course, that O is allocated on stack on typical > architectures, by typical compilers. Yes, of course. I am trying to understand the mechanism behind T'Class variables on ordinary architectures. > O is allocated on stack, just like any other declare-block variable. > (A function/procedure local variable would be just the same.) > O's size is determined at run-time, when it finds out exactly what > type of object it has to hold. So where does the returned value from the function live between the time the function returns and the time space is allocated on the stack for O? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-07 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Matthew Heaney @ 1999-06-08 0:00 ` Robert Dewar 1999-06-08 0:00 ` Markus Kuhn 1999-06-08 0:00 ` Stanley R. Allen 1 sibling, 2 replies; 116+ messages in thread From: Robert Dewar @ 1999-06-08 0:00 UTC (permalink / raw) In article <t7wvxfn75v.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> wrote: > From a little further fooling around, followed by a trip to the Ada RM, > I see that objects of class-wide type can not be record components, which > I guess makes sense, but it doesn't seem very orthogonal to me. Actually it is quite orthogonal and consistent with the rest of the language. X'Class is like String from this point of view, it is a general type, and you need a specific instance to declare an object or a record component of this type. There is another language that you might see here in which String variables are generally permitted, and in that language you would also expect to find X'Class record components (as well as automatic storage management, and a generally rather different semantic level). Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Robert Dewar @ 1999-06-08 0:00 ` Markus Kuhn 1999-06-08 0:00 ` Stanley R. Allen 1999-06-08 0:00 ` Stanley R. Allen 1 sibling, 1 reply; 116+ messages in thread From: Markus Kuhn @ 1999-06-08 0:00 UTC (permalink / raw) Robert Dewar <robert_dewar@my-deja.com> writes: |> In article <t7wvxfn75v.fsf@calumny.jyacc.com>, |> Hyman Rosen <hymie@prolifics.com> wrote: |> > From a little further fooling around, followed by a trip to the Ada RM, |> > I see that objects of class-wide type can not be record components, which |> > I guess makes sense, but it doesn't seem very orthogonal to me. |> |> There is another language that you might see here in which |> String variables are generally permitted, and in that language |> you would also expect to find X'Class record components (as |> well as automatic storage management, and a generally rather |> different semantic level). This is exactly an example of what makes Ada so fascinating but also so challenging to thoroughly understand for a beginner. We have on one side simple low-level languages such as C, where the memory representation of objects is fairly completely visible to the programmer and where it is easy to realize what is going on behind the scenes. On the other hand, we have very high level languages with garbage collection such as Lisp, Scheme, Perl, Python, to some degree also Java. They hide completely from the programmer issues such as memory management and memory layout, they provide a very simple form of orthogonality (everything can contain anything), but they are because of these properties unsuitable for high-performance, low-level, real-time, and safety-critical programming. Ada goes a very rarely seen path in between these clearly separated communities. On one side it is a low-level language such as C that gives the programmer tight control over various representation issues and results in high-performance code. On the other hand it has features such as unconstrained arrays and functions that return variable-length objects that resemble closely more powerful features of real high-level languages such as Scheme and Python, but that are still implementable without the need of a garbage collector or a byte-code interpreter. Experienced programmers know a lot about how languages like C and Scheme work below the hood, but since Ada is somewhere in between, this can at first be rather confusing. Unfortunatelly, none of the textbooks about Ada talk enough about how these features (especially variable-length arrays, types with discriminators, subtypes, etc.) that are not seen much in other languages are usually implemented by compilers. I hope that one day, somebody will write an Ada textbook, that does not just state the various rules of the lannguage (which can be very difficult to remember), but that explains features such as types with discriminators and fucntions returning variable-length arrays based on examples how common compilers such as GNAT implement these. Then the restrictions of these mechanisms will become obvious and have not to be remembered as a seemingly non-orthogonal set of rules. A good paper on how GNAT implements all the features of Ada that are not obvious for a C programmer would also be a very important teaching tool in this respect. Is there anything comparable already available? Markus -- Markus G. Kuhn, Computer Laboratory, University of Cambridge, UK Email: mkuhn at acm.org, WWW: <http://www.cl.cam.ac.uk/~mgk25/> ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Markus Kuhn @ 1999-06-08 0:00 ` Stanley R. Allen 0 siblings, 0 replies; 116+ messages in thread From: Stanley R. Allen @ 1999-06-08 0:00 UTC (permalink / raw) Markus Kuhn wrote: > > Unfortunatelly, none of the textbooks > about Ada talk enough about how these features (especially > variable-length arrays, types with discriminators, subtypes, etc.) that > are not seen much in other languages are usually implemented by > compilers. > > I hope that one day, somebody will write an Ada textbook, that does not just > state the various rules of the lannguage (which can be very difficult to > remember), but that explains features such as types with discriminators > and fucntions returning variable-length arrays based on examples how > common compilers such as GNAT implement these. Then the restrictions > of these mechanisms will become obvious and have not to be remembered > as a seemingly non-orthogonal set of rules. The implementation of some of these features may be useful to explain their use, but making the philosphy behind them more apparent may be the real need. There is, lurking under the "surface" rules of the Ada language, a more or less thoroughly worked out collection of design principles. The orthogonality of the language can only be seen by comprehending these principles. The issue that triggered this response -- the similar rules for unconstrained types and class-wide types ("indefiniteness") -- is an example of one of these hidden principles at work. When I teach the language, I always try to make such principles explicit. Subtypes, generic formal and actual matching rules, type attributes, staticness, and the relationship between elaboration and execution -- are are topics that "fall between the cracks" sometimes, but are essential to grasp in order to make the most effective use of the language. (Speaking of orthogonality, one can only speculate -- unless Mr. Taft addresses it his memoirs one day -- on the influence that the science of chemistry has had on the design of Ada 95. Perhaps even unconsciously so??... ;) -- Stanley Allen mailto:s_allen@hso.link.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Robert Dewar 1999-06-08 0:00 ` Markus Kuhn @ 1999-06-08 0:00 ` Stanley R. Allen 1 sibling, 0 replies; 116+ messages in thread From: Stanley R. Allen @ 1999-06-08 0:00 UTC (permalink / raw) Robert Dewar wrote: > > There is another language that you might see here in which > String variables are generally permitted, and in that language > you would also expect to find X'Class record components (as > well as automatic storage management, and a generally rather > different semantic level). > Nothing but a tease! -- Stanley Allen mailto:s_allen@hso.link.com ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <t7zp2sr6yf.fsf@calumny.jyacc.c <t7emjmmx8w.fsf@calumny.jyacc.com>]
* Re: Ada OO Mechanism [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <t7emjmmx8w.fsf@calumny.jyacc.com> @ 1999-06-08 0:00 ` Larry Kilgallen 1999-06-08 0:00 ` Hyman Rosen 0 siblings, 1 reply; 116+ messages in thread From: Larry Kilgallen @ 1999-06-08 0:00 UTC (permalink / raw) Reply-To: Kilgallen@eisner.decus.org.nospam Organization: LJK Software Lines: 25 In article <t7emjmmx8w.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> writes: > Matthew Heaney <matthew_heaney@acm.org> writes: >> On 07 Jun 1999 15:26:52 -0400, Hyman Rosen <hymie@prolifics.com> wrote: >> However, the declaration >> declare >> S : String := Func_Return_String; >> begin >> is perfectly legal, and so is the declaration >> declare >> O : T'Class := Func_Return_T_Tic_Class; >> begin >> In neither case is heap required. > > And despite that, you said before that the size of O is determined > at run-time, not at compile-time. Also, I looked at some of the code > generated by GNAT, and saw references to a secondary_stack_allocate > (or something like that) function. So the storage for S and O is > allocated somewhere, but it's on the stack? Is this something like > alloca? The fact that GNAT allocates it in one place does not mean all compilers will do it in the same place. Is your question specifically "how does GNAT do this ?" ? Larry Kilgallen ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Larry Kilgallen @ 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Tucker Taft ` (2 more replies) 0 siblings, 3 replies; 116+ messages in thread From: Hyman Rosen @ 1999-06-08 0:00 UTC (permalink / raw) kilgallen@eisner.decus.org (Larry Kilgallen) writes: > The fact that GNAT allocates it in one place does not mean all compilers > will do it in the same place. Is your question specifically "how does > GNAT do this ?" ? I am trying to understand the mechanism behind T'Class. I have been told that the size of such variables is determined at run-time, and also that the heap is not required for such variables. So, to anyone, if you don't mind taking the time to explain, how does <compiler of your choice> implement this? Also, I stated in an earlier message that I thought not allowing T'Class variables in records was not orthogonal, but understandable in light of the above. Now, suppose I need a function that returns a pair of values, one of which is a T'Class and the other a boolean. Is there a way to do this? I can't return a record containing the pair, because I can't have such a record. I assume that a procedure with a pair of out parameters won't work, because the T'Class variable which receives the output must be initialized when declared, and then its tag can't change. So, is there a way? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Hyman Rosen @ 1999-06-08 0:00 ` Tucker Taft 1999-06-08 0:00 ` Brian Rogoff ` (3 more replies) 1999-06-09 0:00 ` Samuel Mize 1999-06-09 0:00 ` Matthew Heaney 2 siblings, 4 replies; 116+ messages in thread From: Tucker Taft @ 1999-06-08 0:00 UTC (permalink / raw) Hyman Rosen wrote: > > kilgallen@eisner.decus.org (Larry Kilgallen) writes: > > The fact that GNAT allocates it in one place does not mean all compilers > > will do it in the same place. Is your question specifically "how does > > GNAT do this ?" ? > > I am trying to understand the mechanism behind T'Class. I have been told > that the size of such variables is determined at run-time, and also that > the heap is not required for such variables. > > So, to anyone, if you don't mind taking the time to explain, how does > <compiler of your choice> implement this? Several compilers use what is called a "secondary stack" (or a "data stack"), as distinct from the "primary stack" (or "control stack"). The secondary stack is generally managed in a mark/release manner. There is one per task. On entry to a subprogram or block the secondary stack is marked, and prior to exit, the secondary stack is released. In the interim objects of run-time-determined size may be allocated as needed. A pointer to the object is generally stored on the primary stack. For functions that return objects of size unknown to the caller, the function creates the object on (or copies the object to) the secondary stack, and then returns from the function *without* releasing the secondary stack. The caller takes care of releasing the secondary stack once they are through with using the returned object. There are other compilers that use "local" heaps, or other heap-based mechanisms. They all still typically use some kind of mark/release, though it may be a mark/release on a linked-list of objects, rather than on a secondary stack. > > Also, I stated in an earlier message that I thought not allowing T'Class > variables in records was not orthogonal, but understandable in light of > the above. Now, suppose I need a function that returns a pair of values, > one of which is a T'Class and the other a boolean. Is there a way to do > this? I can't return a record containing the pair, because I can't have > such a record. I assume that a procedure with a pair of out parameters > won't work, because the T'Class variable which receives the output must > be initialized when declared, and then its tag can't change. So, is there > a way? No. Once you need to combine a class-wide value with something else, you will have to use the heap explicitly. (I suppose you could add an "access Boolean" parameter to a function if you wanted to return a Boolean as well as a class-wide value.) As pointed out by Markus Kuhn, Ada goes one (important, in my mind) step beyond C/C++ by providing built-in, safe support for objects whose size is not known at compile-time. However this support is not completely flexible -- it is generally restricted to cases where the size is known at the time when the object is declared. Explicit use of the heap is the fallback approach when you need more flexibility than is directly supported. -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Distributed IT Solutions (www.averstar.com/tools) AverStar (formerly Intermetrics, Inc.) Burlington, MA USA ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Tucker Taft @ 1999-06-08 0:00 ` Brian Rogoff [not found] ` < <375E92CB.27850620@averstar.com> ` (2 subsequent siblings) 3 siblings, 0 replies; 116+ messages in thread From: Brian Rogoff @ 1999-06-08 0:00 UTC (permalink / raw) On Tue, 8 Jun 1999, Tucker Taft wrote: > Hyman Rosen wrote: > > Also, I stated in an earlier message that I thought not allowing T'Class > > variables in records was not orthogonal, but understandable in light of > > the above. Now, suppose I need a function that returns a pair of values, > > one of which is a T'Class and the other a boolean. Is there a way to do > > this? I can't return a record containing the pair, because I can't have > > such a record. I assume that a procedure with a pair of out parameters > > won't work, because the T'Class variable which receives the output must > > be initialized when declared, and then its tag can't change. So, is there > > a way? > > No. Once you need to combine a class-wide value with something else, > you will have to use the heap explicitly. (I suppose you could > add an "access Boolean" parameter to a function if you wanted to return > a Boolean as well as a class-wide value.) This kind of problem is solved in some languages, like Common Lisp and Dylan, with multiple value return and others, like ML and Haskell, with tuples. Was the prospect of such a mechanism for Ada considered (yes I'm sure :-) and if so why was it rejected? Seeing as Ada has aggregates, it seems to me that multiple value return would also have been a feature. Using access params here to simulate functions with out params looks really ugly to me. -- Brian ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: < <375E92CB.27850620@averstar.com>]
* Re: Ada OO Mechanism [not found] ` < <375E92CB.27850620@averstar.com> @ 1999-06-09 0:00 ` Brian Rogoff 1999-06-14 0:00 ` Robert A Duff 0 siblings, 1 reply; 116+ messages in thread From: Brian Rogoff @ 1999-06-09 0:00 UTC (permalink / raw) On Wed, 9 Jun 1999, Tucker Taft wrote: > Brian Rogoff wrote: > > ... > > This kind of problem is solved in some languages, like Common Lisp and > > Dylan, with multiple value return and others, like ML and Haskell, with > > tuples. Was the prospect of such a mechanism for Ada considered (yes I'm > > sure :-) and if so why was it rejected? Seeing as Ada has aggregates, it > > seems to me that multiple value return would also have been a feature. > > In Ada, multiple value return is not significantly different > from returning a record. However, the problem we are trying > to solve is not multiple value return, but rather returning > objects of size unknown at compile-time without using the heap. Yes, I know. I can understand why it makes sense that a record cannot contain unconstrained types, but I don't understand why a suitable generalization of Ada's ability to return unconstrained types could not be made to solve the problem being discussed *without* forcing a heap based mechanism on Ada. An example might be returning two strings on the stack. > Common Lisp, Dylan, ML, and Haskell all rely heavily on heap-based > mechanism, and what is passed around are references (or tuples > of references). It was an unfortunate choice of example languages, but I think you'll agree that the reliance on the heap is mostly an implementation issue, at least in the case of ML (*). Sorry for the confusion, I just don't know of any system programming languages with multiple value return. Incidentally, I'm not suggesting that this would be a good idea for Ada, I am just interested in whether it was discussed and if so what were the reasons for not doing it. I can think of a few myself... > References, and records or arrays of references, > are no problem in Ada either. The challenge is to avoid the heap, > and I believe Ada goes further than almost any language in accomplishing > that. But as pointed out, there are some limitations, which result > in the heap being necessary when things get too complicated. Agreed. > > Using access params here to simulate functions with out params looks really > > ugly to me. > > Access parameters are the Ada 95 way to give functions "out" parameters. > It has the advantage of making the OUT parameters quite visible, thanks > to the use of 'Access at the call point. Note that many languages don't > support OUT parameters at all. All they support is passing references. Sure, in C I don't mind doing this, but when I write Ada my "Ada mindset" is such that this seems like a "workaround". If it really was a good idea to make out parameters visible then I'd imagine I should always use 'Access since (as Robert Dewar likes to point out) we should favor the reader and maintenance programer over the writer. That doesn't mean that I won't often do this, just that unless I had a very good reason for avoiding heap access I'd use one of the other workarounds. -- Brian (*) There are ML compilers which don't use garbage collectors, relying on a technique called region inference which (roughly speaking) use a mark-release style allocator with mark and release points inferred automatically. Its also true that Ada's avoidance of the heap is also implementation dependent. Ada=>JVM compilers probably hit the heap quite a bit :-). ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-09 0:00 ` Brian Rogoff @ 1999-06-14 0:00 ` Robert A Duff 0 siblings, 0 replies; 116+ messages in thread From: Robert A Duff @ 1999-06-14 0:00 UTC (permalink / raw) Brian Rogoff <bpr@shell5.ba.best.com> writes: > Yes, I know. I can understand why it makes sense that a record cannot > contain unconstrained types, but I don't understand why a suitable > generalization of Ada's ability to return unconstrained types could not be > made to solve the problem being discussed *without* forcing a heap based > mechanism on Ada. An example might be returning two strings on the stack. Well, you can return two strings on the stack by returning a record that looks like this: type String_Pair(Length1, Length2: natural) is record String1: String(1..Length1); String2: String(1..Length2); end record; But you can't do that with class-wide, because there's no constraint to constrain the tag of an object, analogous to the constraints on the upper bounds of the above strings. Adding such a concept to the language would add functionality, but would also add complexity. Probably not worth it. - Bob -- Change robert to bob to get my real email address. Sorry. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Tucker Taft 1999-06-08 0:00 ` Brian Rogoff [not found] ` < <375E92CB.27850620@averstar.com> @ 1999-06-09 0:00 ` Robert Dewar 1999-06-09 0:00 ` Tucker Taft 3 siblings, 0 replies; 116+ messages in thread From: Robert Dewar @ 1999-06-09 0:00 UTC (permalink / raw) In article <375D9A3D.E1CCCC63@averstar.com>, Tucker Taft <stt@averstar.com> wrote: > For functions that return objects of size unknown to the caller, the > function creates the object on (or copies the object to) the secondary > stack, and then returns from the function *without* releasing the > secondary stack. The caller takes care of releasing the secondary stack > once they are through with using the returned object. > > There are other compilers that use "local" heaps, or other heap-based > mechanisms. They all still typically use some kind of mark/release, > though it may be a mark/release on a linked-list of objects, rather > than on a secondary stack. By far the most efficient method of handling variable length returned values is to return with the stack pointer depressed so that the newly created value is still available. However this cannot be done without wandering a bit outside the standard ABI, and is thus infeasible in GNAT, which always uses the standard ABI calling sequence. Actually there is one routine alloca, which works the same way, and indeed alloca has to be built in on many compilers, precisely because it does not fit the standard ABI calling sequence. Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Tucker Taft ` (2 preceding siblings ...) 1999-06-09 0:00 ` Robert Dewar @ 1999-06-09 0:00 ` Tucker Taft 3 siblings, 0 replies; 116+ messages in thread From: Tucker Taft @ 1999-06-09 0:00 UTC (permalink / raw) Brian Rogoff wrote: > ... > This kind of problem is solved in some languages, like Common Lisp and > Dylan, with multiple value return and others, like ML and Haskell, with > tuples. Was the prospect of such a mechanism for Ada considered (yes I'm > sure :-) and if so why was it rejected? Seeing as Ada has aggregates, it > seems to me that multiple value return would also have been a feature. In Ada, multiple value return is not significantly different from returning a record. However, the problem we are trying to solve is not multiple value return, but rather returning objects of size unknown at compile-time without using the heap. Common Lisp, Dylan, ML, and Haskell all rely heavily on heap-based mechanism, and what is passed around are references (or tuples of references). References, and records or arrays of references, are no problem in Ada either. The challenge is to avoid the heap, and I believe Ada goes further than almost any language in accomplishing that. But as pointed out, there are some limitations, which result in the heap being necessary when things get too complicated. > Using access params here to simulate functions with out params looks really > ugly to me. Access parameters are the Ada 95 way to give functions "out" parameters. It has the advantage of making the OUT parameters quite visible, thanks to the use of 'Access at the call point. Note that many languages don't support OUT parameters at all. All they support is passing references. > -- Brian -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Distributed IT Solutions (www.averstar.com/tools) AverStar (formerly Intermetrics, Inc.) Burlington, MA USA ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Tucker Taft @ 1999-06-09 0:00 ` Samuel Mize 1999-06-09 0:00 ` Matthew Heaney 2 siblings, 0 replies; 116+ messages in thread From: Samuel Mize @ 1999-06-09 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > I am trying to understand the mechanism behind T'Class. I have been told > that the size of such variables is determined at run-time, and also that > the heap is not required for such variables. This specific question has been beat to death, but I wanted to point out a generality. When folks say that an Ada feature doesn't use the heap, they usually mean that it doesn't require the programmer to explicitly use the heap. The run-time has to create and delete scratch areas from time to time, and it's not defined where these are. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Tucker Taft 1999-06-09 0:00 ` Samuel Mize @ 1999-06-09 0:00 ` Matthew Heaney 2 siblings, 0 replies; 116+ messages in thread From: Matthew Heaney @ 1999-06-09 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > Also, I stated in an earlier message that I thought not allowing T'Class > variables in records was not orthogonal, but understandable in light of > the above. Now, suppose I need a function that returns a pair of values, > one of which is a T'Class and the other a boolean. Is there a way to do > this? Not really, no. Here are some ideas: 1) return a record containing a class-wide component allocated on the heap type RT is record O : T_Class_Access; B : Boolean; end record; function Func_Ret_RT return RT; 2) Break in the function apart into two functions: function Func_Ret_T_Tic_Class return T'Class; function Func_Ret_Boolean return Boolean; This doesn't preserve atomicity, however. (But that's not always an issue anyway.) 3) Embed the Boolean value in state of the object: function Func_Ret_T_Tic_Class return T'Class; function Func_Ret_Boolean (O : T) return Boolean; > I can't return a record containing the pair, because I can't have > such a record. That is correct. Although, if you follow approach 1), you can put the class-wide value on the heap. > I assume that a procedure with a pair of out parameters won't work, > because the T'Class variable which receives the output must be > initialized when declared, and then its tag can't change. Yes, that is correct. > So, is there a way? See the three bullets above. ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <t7zp2sr6yf.fsf@calumny.jyacc.c <t7r9nmz8ou.fsf@calumny.jyacc.com>]
* Re: Ada OO Mechanism [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <t7r9nmz8ou.fsf@calumny.jyacc.com> @ 1999-06-08 0:00 ` Larry Kilgallen 1999-06-08 0:00 ` Hyman Rosen 0 siblings, 1 reply; 116+ messages in thread From: Larry Kilgallen @ 1999-06-08 0:00 UTC (permalink / raw) Reply-To: Kilgallen@eisner.decus.org.nospam Organization: LJK Software Lines: 21 In article <t7r9nmz8ou.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> writes: > kilgallen@eisner.decus.org (Larry Kilgallen) writes: >> The fact that GNAT allocates it in one place does not mean all compilers >> will do it in the same place. Is your question specifically "how does >> GNAT do this ?" ? > > I am trying to understand the mechanism behind T'Class. I have been told > that the size of such variables is determined at run-time, and also that > the heap is not required for such variables. If your compiler stores it entirely on the stack, the heap is not required. Obviously some compiler could store it on the heap, in which case the statement "all compilers store it entirely on the stack" would be wrong. At a more basic level, storing a variable length structure on the stack requires that the machine code alter the amount of stack consumed on one call from the next. Many other languages do not have programmer- visible constructs that do such a run-time determination, so perhaps that is what makes the concept seem strange. Larry Kilgallen ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Larry Kilgallen @ 1999-06-08 0:00 ` Hyman Rosen 1999-06-14 0:00 ` Robert A Duff 0 siblings, 1 reply; 116+ messages in thread From: Hyman Rosen @ 1999-06-08 0:00 UTC (permalink / raw) kilgallen@eisner.decus.org (Larry Kilgallen) writes: > At a more basic level, storing a variable length structure on the stack > requires that the machine code alter the amount of stack consumed on > one call from the next. Many other languages do not have programmer- > visible constructs that do such a run-time determination, so perhaps > that is what makes the concept seem strange. They also don't have functions which return variable-length objects. Where does the function return value live between the time the function returns and the time that space is allocated for the variable on the stack, using the size information in the return value? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-08 0:00 ` Hyman Rosen @ 1999-06-14 0:00 ` Robert A Duff 0 siblings, 0 replies; 116+ messages in thread From: Robert A Duff @ 1999-06-14 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > kilgallen@eisner.decus.org (Larry Kilgallen) writes: > > At a more basic level, storing a variable length structure on the stack > > requires that the machine code alter the amount of stack consumed on > > one call from the next. Many other languages do not have programmer- > > visible constructs that do such a run-time determination, so perhaps > > that is what makes the concept seem strange. > > They also don't have functions which return variable-length objects. > Where does the function return value live between the time the > function returns and the time that space is allocated for the variable > on the stack, using the size information in the return value? One model is to just leave it on the stack. The function return then jumps back to where it came from, but does *not* chop back the stack. At the call site, the caller then copies the function result to wherever it belongs. Or, if the call site is another return statement, it just leaves it where it is, and lets the caller's caller deal with it. - Bob -- Change robert to bob to get my real email address. Sorry. ^ permalink raw reply [flat|nested] 116+ messages in thread
[parent not found: <t7zp2sr6yf.fsf@calumny.jyacc.c <375d9a3d.e1cccc63@averstar.com>]
* Re: Ada OO Mechanism [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <375d9a3d.e1cccc63@averstar.com> @ 1999-06-09 0:00 ` Larry Kilgallen 1999-06-09 0:00 ` Tucker Taft 0 siblings, 1 reply; 116+ messages in thread From: Larry Kilgallen @ 1999-06-09 0:00 UTC (permalink / raw) Reply-To: Kilgallen@eisner.decus.org.nospam Organization: LJK Software Lines: 14 In article <375D9A3D.E1CCCC63@averstar.com>, Tucker Taft <stt@averstar.com> writes: > Several compilers use what is called a "secondary stack" (or a "data stack"), > as distinct from the "primary stack" (or "control stack"). > The secondary stack is generally managed in a mark/release manner. > There is one per task. So in such compilers, how does specification of task (stack) size relate to the primary and/or secondary stack ? Do any compilers that use this method also support unlimited (well, at least unspecified) stack size for the main task ? For both stacks ? Larry Kilgallen ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-09 0:00 ` Larry Kilgallen @ 1999-06-09 0:00 ` Tucker Taft 0 siblings, 0 replies; 116+ messages in thread From: Tucker Taft @ 1999-06-09 0:00 UTC (permalink / raw) Larry Kilgallen wrote: > > Reply-To: Kilgallen@eisner.decus.org.nospam > Organization: LJK Software > Lines: 14 > > In article <375D9A3D.E1CCCC63@averstar.com>, Tucker Taft <stt@averstar.com> writes: > > > Several compilers use what is called a "secondary stack" (or a "data stack"), > > as distinct from the "primary stack" (or "control stack"). > > The secondary stack is generally managed in a mark/release manner. > > There is one per task. > > So in such compilers, how does specification of task (stack) size > relate to the primary and/or secondary stack ? It varies. In some, it is the sum of the space given to the primary and secondary stack, which "grow" toward each other. In others, it only controls the primary stack, and the secondary stack is represented as an arbitrarily extendable linked-list of large chunks. There are probably other combinations as well. > Do any compilers that use this method also support unlimited (well, > at least unspecified) stack size for the main task ? For both stacks ? I would guess that many compilers that run on Unix-like timesharing systems use the automatic stack extension feature to handle the main primary stack, and either have a fixed size for the secondary stack, or represent the secondary stack using chunks and have no fixed limit. On most embedded systems, I suspect that the main task's primary and secondary stack sizes are set at link-time. > Larry Kilgallen -- -Tucker Taft stt@averstar.com http://www.averstar.com/~stt/ Technical Director, Distributed IT Solutions (www.averstar.com/tools) AverStar (formerly Intermetrics, Inc.) Burlington, MA USA ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Richard D Riehle @ 1999-05-25 0:00 ` Brian Rogoff 1999-05-25 0:00 ` Jim 1999-05-26 0:00 ` Robert Dewar 1999-05-25 0:00 ` Samuel Mize ` (2 subsequent siblings) 4 siblings, 2 replies; 116+ messages in thread From: Brian Rogoff @ 1999-05-25 0:00 UTC (permalink / raw) On 25 May 1999, Hyman Rosen wrote: > Samuel Mize <smize@imagin.net> writes: > > ... snip ... > > > Did you intend that paragraph to sound contentious? To my ear, > > at least, it has rather a "you're all liars, I'm naming names" > > sound to it -- I hope that isn't what you meant. > > I wanted it to sound somewhat contentious. The named people each > claimed in a posting that there were object-oriented techniques > that were harder, or less elegant, in C++ than in Ada. I asked > for examples with the thought that perhaps the posters didn't know > C++ as well as they knew Ada, and were therefore perhaps mistaken. > There were responses, but no code, so I got a little testy. I think its true that a lot of people have had this discussion a few times on c.l.a., so when someone mentions symmetric binary operators they imagine you've RTFM, or in this case the programming language FAQ, or the Rationale, or what have you. If you're interested in some other cases where the Ada mechanism is a little nicer, there are lots of examples of dispatching on function result that are easier, IMO of course, than the approaches in C++. Check out http://www.adahome.com/FAQ/programming.html#constructors http://stwi.weizmann.ac.il/g-cs/benari/articles/func.htm for examples. Another thing is that unless I'm missing something, C++ does not provide constrained genericity so you have to use workarounds like that in http://lazy.ton.tut.fi/~esap/instructive/simulating-constrained-genericity.html so your example Ada code that you wrote in another message is in fact a good example of a case where Ada is nicer :-) Incidentally, I tend to agree with you about automatic instantiation, and that was also discussed here. I tend to think that it shortens the code by eliminating noise instantiations, at least in quite a few examples I've seen. There are a number of things I like better about C++, though I think my "ideal" systems programming language would look mostly like Ada. -- Brian ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Brian Rogoff @ 1999-05-25 0:00 ` Jim 1999-05-26 0:00 ` Robert Dewar 1 sibling, 0 replies; 116+ messages in thread From: Jim @ 1999-05-25 0:00 UTC (permalink / raw) folks: found this related to this topic. from adahome: " (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.) " ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Brian Rogoff 1999-05-25 0:00 ` Jim @ 1999-05-26 0:00 ` Robert Dewar 1999-05-26 0:00 ` Brian Rogoff 1 sibling, 1 reply; 116+ messages in thread From: Robert Dewar @ 1999-05-26 0:00 UTC (permalink / raw) In article <Pine.BSF.4.10.9905252005460.2577-100000@shell5.ba.best.com>, Brian Rogoff <bpr@shell5.ba.best.com> wrote: > Incidentally, I tend to agree with you about automatic > instantiation, and that was also discussed here. I tend to > think that it shortens the code generally this is an invalid argument from the Ada point of view, without additional justification that this shortening makes it easier to *read* and *maintain* the code. > by eliminating noise instantiations If this really is noise, that does not help the maintainer of the code, then that is indeed a fair point. However many people feel (including me) that the explicit instantiations most often are helpful to the maintainers of the code, and that implicit instantiations, while allowing neat things to be written, can generate code that is over-obscure. As always, talking about generalities is usually useless, and especially in a case like this, where it depends very much on the specific case, we should really have a specific case to talk about. --== Sent via Deja.com http://www.deja.com/ ==-- ---Share what you know. Learn what you don't.--- ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Robert Dewar @ 1999-05-26 0:00 ` Brian Rogoff 0 siblings, 0 replies; 116+ messages in thread From: Brian Rogoff @ 1999-05-26 0:00 UTC (permalink / raw) On Wed, 26 May 1999, Robert Dewar wrote: > In article > <Pine.BSF.4.10.9905252005460.2577-100000@shell5.ba.best.com>, > Brian Rogoff <bpr@shell5.ba.best.com> wrote: > > Incidentally, I tend to agree with you about automatic > > instantiation, and that was also discussed here. I tend to > > think that it shortens the code > > generally this is an invalid argument from the Ada point of > view, without additional justification that this shortening > makes it easier to *read* and *maintain* the code. Indeed, although I think it safe to say that if it didn't make it any *harder* to read and maintain code, that shortening wouldn't be a bad idea. But that's academic, those factors are seldom (never?) orthogonal. > > by eliminating noise instantiations > > If this really is noise, that does not help the maintainer of > the code, then that is indeed a fair point. However many people > feel (including me) that the explicit instantiations most often > are helpful to the maintainers of the code, and that implicit > instantiations, while allowing neat things to be written, can > generate code that is over-obscure. The same thing can be said for overloading and use clauses too, though I much appreciate overloading and use clauses and feel that used well they leads to easier to read code. Automatic instantiation is in the same category IMO. > As always, talking about generalities is usually useless, and > especially in a case like this, where it depends very much on > the specific case, we should really have a specific case to > talk about. There are a few examples in the Tri-Ada '91 paper "Automatic Instantiation in Ada". Note that the proposal there was an upward compatible extension to Ada 83 which really just made some, not all, instantiations optional. It is also unlike the C++ template mechanism in that it doesn't support things like template metaprogramming. If you look at any of the STL in Ada libraries, you'll also see examples of places where autoinstantiation would be nice. I'll cook up some examples for you, if you find the examples in the Tri-Ada paper unconvincing. I certainly believe from my experiences doing STLish stuff in Ada that such a mechanism would make that style of programming more convenient, and by convenient here I mean for the reader as well as the writer. My experience with ML also has a part in convincing me that a little bit of type inference is OK, though I think that explicit typing is best most of the time. -- Brian ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Brian Rogoff @ 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Chris 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Samuel Mize 4 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-25 0:00 UTC (permalink / raw) I'm combining responses to two messages here. Hyman Rosen <hymie@prolifics.com> wrote: >Samuel Mize <smize@imagin.net> writes: >> THE QUESTION: how does one do "mix-in" classes in C++? I'd bet a >> nickel that you can, but I don't know the specific mechanism. Then you answered the question. Thanks; I figured one could do it. I'm using lines of "- " to separate major sections. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >> - The class is the primary form of data encapsulation. > >Classes support static data and function members, and nested classes. >I believe that this gives C++ the equivalent of Ada's packages. The difference is that, in Ada, encapsulation is distinct from the object-oriented notion of "class." Certainly a C++ class provides encapsulation. It also provides more, and this may cause confusion when you want to encapsulate something without indicating that it meets the OO notion of a "class." There may be object-oriented approaches that uses this distinction, but I don't have a reference handy, and I don't make this claim. I do know that this distinction is extremely useful in a mixed-method environment, e.g., object-oriented and procedural elements working together. That doesn't directly address "an OO method that's harder in C++." It does point out that an OO/procedural integrated system may be less clear in C++, as the reader must determine which classes are classes, and which classes are not classes but just encapsulations of non-class entities. So, if we consider mixed-method programming to be a form of OO, we can argue that this is a form of OO that is not as well supported by C++ as by Ada. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >> - Each "message" (implemented as a dispatching function call) goes >> to exactly one object (or class). Any other objects mentioned are >> passive arguments. > >How is this different from Ada? Does Ada allow dispatching on more than >one argument? Yes, see my other message. As you noted in reply to it: >Samuel Mize <smize@imagin.net> writes: >> -- This dispatches on both parameters, so they have to match >> -- at run-time >> procedure Operation_4 (A: A_Type; B: B_Type); > >(Do you mean B: A_Type ?) Also, to your question: >When you say "match at runtime" do you mean that their dynamic types >must be the same? Does the code raise an exception if they happen not >to match? I'll detail this for you in a while, but I need to refer back to the ARM and bone up first. >If I were to code this in C++, I could do the following: > > void Operation_4(A_Type &A, A_Type &B) > { > if (typeid(A) != typeid(B)) > throw "Mismatched types!"; > A.Operation_4(B); > } You can manually code it up, but that doesn't mean the language supports it -- rather the reverse. By a similar argument, one can claim to do full-up object-oriented programming in C. Indeed, the X-windows system is done that way (or used to be, anyway -- I haven't looked at it for a few years). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >> - When an object sends a message, it waits for the called object >> to complete its processing of the message (that is, for the return >> of the function call) before continuing. >> - One thread of control calls all objects; they are not independent >> active entities. > >Well, no argument there. C++ does not have a language-defined parallel >processing capability, and Ada is absolutely superior in that regard. >However, I would say that this is generally considered orthogonal to >object-oriented programming, since your statement above is equally true >if you replace objects and messages with plain function calls. There are object-oriented methods of analysis and design that view all the objects in a system as inherently parallel, independent actors. This is called the Actor model, and there are languages that encapsulate it. In this method, parallel independent execution is not orthogonal to object-oriented programming; the method considers independence of execution to be integral to their definition. I don't say that OO programming inherently includes parallelism. I do say that there exist methods of OO programming which consider parallelism integral to the definition of an object. >I think including parallel behavior in your definition >of OO is stretching that definition beyond any accepted usage. My assertion was that there are OO methods that are harder to implement in C++ than in Ada. Here is an example. The fact that single-thread OO methods don't consider parallelism to be integral to the concept of "objects" does not invalidate other method that do. It isn't as popular as the C++ model, as I said. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >> Did you intend that paragraph to sound contentious? To my ear, >> at least, it has rather a "you're all liars, I'm naming names" >> sound to it -- I hope that isn't what you meant. > >I wanted it to sound somewhat contentious. The named people each >claimed ... >There were responses, but no code, so I got a little testy. Well, that's too bad. There is a class of people (in Ada terms, a type :-) called a net.loon. I don't think you are one. But one thing that net.loons often do is to demand that some other poster provide hard evidence, right away, in whatever form they deem most appropriate, to support some stray comment. When the evidence doesn't show up on demand, the net.loon's next step is to demand that the other poster publicly admit not only that they might be mistaken, but that they were out-and-out lying and knew it. Following this come other accusations, obscenities, and sometimes mail bombs and other electronic harassment. I think you can see why people would just ignore or kill-file anyone who seems to be starting down that road with them. So I would strongly suggest that you take a more "chilled out" approach in posting. Understand that people may hold and express opinions without having statistics or code examples handy to support them. They may even hold and express opinions with nothing behind them but hot air, and that's perfectly OK on the net. They may also not see your question for days, if at all. News propagation can be unreliable. And, most of us have lots of other things to do, like making a living and living a life, and digging up specifics for a net argument is way down on our list of priorities. Especially when someone focuses in on one sentence out of a 175-line post, ignores the rest of it, and bears down demanding hard evidence; and after a couple of days, starts throwing my name around in another post as one of Those People who didn't deliver evidence on demand. And that's about as contentious as I want to get on the net. I hope to have fruitful and pleasant discussions with you in the future. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Samuel Mize @ 1999-05-25 0:00 ` Chris 1999-05-25 0:00 ` David Botton 1999-05-27 0:00 ` Samuel Mize 0 siblings, 2 replies; 116+ messages in thread From: Chris @ 1999-05-25 0:00 UTC (permalink / raw) In article <7if7oj$bee@news1.newsguy.com>, Samuel says... > > >I do know that this distinction is extremely useful in a mixed-method >environment, e.g., object-oriented and procedural elements working >together. > I don't think it leads to clear design when one part of the program is done in OO ways, while another part is not. one either uses all OO, or all procedural. don't you agree? Chris ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Chris @ 1999-05-25 0:00 ` David Botton 1999-05-27 0:00 ` Aidan Skinner 1999-05-27 0:00 ` Samuel Mize 1 sibling, 1 reply; 116+ messages in thread From: David Botton @ 1999-05-25 0:00 UTC (permalink / raw) I find that the flexibility often lends itself to very clear designs. Here and there I have been working on a cross platform set of GUI classes. By combining a number of different methods of design I created a very fluid and easy to use set of classes. (I will set up a project page for the classes soon in the Ada Lab - http://www.adapower.com/lab once I finish off a couple dead lines) If Perl is the duct tape of programming languages, Ada is the Rambo knife of engineering. (OK maybe swiss army fit better ...) David Botton Chris wrote: > > In article <7if7oj$bee@news1.newsguy.com>, Samuel says... > > > > > > >I do know that this distinction is extremely useful in a mixed-method > >environment, e.g., object-oriented and procedural elements working > >together. > > > > I don't think it leads to clear design when one part of the > program is done in OO ways, while another part is not. > > one either uses all OO, or all procedural. > > don't you agree? > > Chris > ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` David Botton @ 1999-05-27 0:00 ` Aidan Skinner 1999-05-27 0:00 ` Gautier 0 siblings, 1 reply; 116+ messages in thread From: Aidan Skinner @ 1999-05-27 0:00 UTC (permalink / raw) On Tue, 25 May 1999 22:25:38 -0400, David Botton <David@Botton.com> wrote: >If Perl is the duct tape of programming languages, Ada is the Rambo >knife of engineering. (OK maybe swiss army fit better ...) Personally leatherman is my knife of choice... you can do all you can do with a swiss army knife, but it's better constructed and has a couple of nifty features I've not seen on a swiss army knife (like pliers, wire cutters/strippters etc.). ;) - Aidan (knife flame war anybody?) -- http://www.skinner.demon.co.uk/aidan/ Real men whistle ed commands at 300 baud into a can. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Aidan Skinner @ 1999-05-27 0:00 ` Gautier 0 siblings, 0 replies; 116+ messages in thread From: Gautier @ 1999-05-27 0:00 UTC (permalink / raw) > Personally leatherman is my knife of choice... you can do all you can > do with a swiss army knife, but it's better constructed and has a > couple of nifty features I've not seen on a swiss army knife (like > pliers, wire cutters/strippters etc.). > > ;) > > - Aidan (knife flame war anybody?) OK! Pliers are not in the predefined library of a swiss knife, of course. _But_ as for cutting or stripping wires, I claim that the main blade is a nice generic tool for it! -- Gautier -------- http://members.xoom.com/gdemont/ ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Chris 1999-05-25 0:00 ` David Botton @ 1999-05-27 0:00 ` Samuel Mize 1 sibling, 0 replies; 116+ messages in thread From: Samuel Mize @ 1999-05-27 0:00 UTC (permalink / raw) Chris <Chris@newsguy.com> wrote: > In article <7if7oj$bee@news1.newsguy.com>, Samuel says... >> >>I do know that this distinction is extremely useful in a mixed-method >>environment, e.g., object-oriented and procedural elements working >>together. >> > > I don't think it leads to clear design when one part of the > program is done in OO ways, while another part is not. > > one either uses all OO, or all procedural. > > don't you agree? Nope. But then I've worked on very large systems, with multiple fairly independent subsystems interacting inside the language. For instance, we had an object-oriented design which needed object persistence -- that is, many objects stored their attributes between executions of the system, re-reading their current state at start-up. The repository for these objects was really just a simple data base in this design, and when we tried to switch it to an object-oriented implementation it was much less clear, less maintainable, and slower. Another example would be a process control system that interacts with things like inventory control and materials routing. I could easily imagine that you would want to implement safety-critical control loops in a very controlled procedural fashion -- in this area, you are inherently thinking about actions more than objects anyway. Then you could interface this to an object-oriented representation of the physical objects being manipulated. In short, I've worked in mixed-method environments, and as long as you clearly define where each method is going to be used, it's quite useful and powerful. At SOME point you stop doing OO work and switch to a procedural model, at least when implementing a class's method bodies. Unless, of course, you're coding in something like Smalltalk that is object-oriented all the way down to integers (I understand). I don't think you'll sell the argument that this is necessary, or even clearer to most people than procedurally-coded methods. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen ` (2 preceding siblings ...) 1999-05-25 0:00 ` Samuel Mize @ 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Hyman Rosen 1999-05-27 0:00 ` Samuel Mize 4 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-27 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > Samuel Mize <smize@imagin.net> writes: >> -- This dispatches on both parameters, so they have to match >> -- at run-time >> procedure Operation_4 (A: A_Type; B: B_Type); > > (Do you mean B: A_Type ?) > > Thanks, this is the kind of example I meant! This is something that > C++ can't do by itself. When you say "match at runtime" do you mean > that their dynamic types must be the same? Does the code raise an > exception if they happen not to match? Yep. I said elsewhere I'd bone up on this and explain it. Here goes. I haven't been actually using this for a couple of years (dang it), so everybody else backstop me and catch any errors. In a call on a potentially dispatching function or procedure, all the tags of the controlling parameter values have to match, or you get a constraint error at run-time. And, they must be all statically tagged or all dynamically tagged. A value can be statically tagged, dynamically tagged, or tag indeterminate. - It's statically tagged if it is of a specific tagged type. - It's dynamically tagged if it's of a class-wide type. - It's tag indeterminate ONLY if it's a function call, AND its parameters (if any) don't determine its tag. (Such a function call must be able to determine the tag to use for its result from the context of the call.) Note that the tag of a function call depends on the tags of its parameters. It's statically or dynamically tagged, whichever the parameters are. If there are no statically or dynamically tagged parameters, the call is tag indeterminate, and you have to be able to tell from the context of the call what tag to use. Here is a little example code. Given the package: package T_Types is type T1 is tagged null record; procedure Op1 (P1: T1; P2: T1); type T1_Class_Access is access T1'Class; type T1_1 is new T1 with null record; -- implicit op1 declared here type T2 is tagged null record; procedure Op1 (P1: T1'class; P2: T2); end t_types; And the following data items: V1: T1; V1_1: T1_1; V1_Class_Access: T1_Class_Access := new T1; V2: T2; Then we can have the following calls, some of which are illegal at compile time and one of which raises Constraint_Error at run time: --------- -- DISPATCHING TO SUBTYPES OF T1 --------- -- legal -- static call to T1.op1 op1 (V1, V1); -- not legal, tags must match --op1 (V1, V1_1); -- not legal, must both be either static or dynamic tagged --op1 (V1, V1_Class_Access.all); -- legal -- dispatching call to op1 in some descendant of T1 op1 (V1_Class_Access.all, V1_Class_Access.all); -- legal -- both are now dynamically tagged op1 (T1'Class (V1), V1_Class_Access.all); -- legal at compile time, but fails at run time because the -- tags don't match --op1 (T1'Class (V1_1), V1_Class_Access.all); --------- -- DISPATCHING TO SUBTYPES OF T2 --------- -- all legal op1 (V1, V2); op1 (V1_1, V2); op1 (V1_Class_Access.all, V2); I hope you find this of some interest. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Samuel Mize @ 1999-05-27 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby 1999-05-28 0:00 ` Samuel Mize 0 siblings, 2 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-27 0:00 UTC (permalink / raw) Samuel Mize <smize@imagin.net> writes: > I hope you find this of some interest. I'm trying to wrap my head around this class-wide type stuff. I'm still at that stage of pre-clarity confusion :-) Here's some code I threw at gnat, based on Richard D. Riehle's example. -- in ft.ads package ft is m: boolean; type S is null record; a_f: S; type T is abstract tagged null record; function Get(F: S) return T is abstract; function GetC(F: S) return T'Class; type A is new T with null record; function Get(F: S) return A; a_a: A; type B is new T with null record; function Get(F: S) return B; a_b: B; end; -- in ft.adb package body ft is function GetC(F: S) return T'Class is begin if m then return a_a; else return a_b; end if; end; z: T'Class := GetC(a_f); function Get(F: S) return A is begin return a_a; end; function Get(F: S) return B is begin return a_b; end; begin z := Get(a_f); end; Gnat complains about the assignment to z: ft.adb:8:14: ambiguous expression (cannot resolve "Get") ft.adb:8:14: possible interpretation at ft.ads:12 ft.adb:8:14: possible interpretation at ft.ads:9 ft.adb:8:14: possible interpretation at ft.ads:6 From reading the Rationale, I thought that the assignment to z would result in a dispatching call to Get, using the tag of z that was set at its initialization. What am I doing wrong here? How do controlling return types work? ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Hyman Rosen @ 1999-05-28 0:00 ` Laurent Guerby 1999-05-28 0:00 ` Richard D Riehle 1999-05-28 0:00 ` Samuel Mize 1 sibling, 1 reply; 116+ messages in thread From: Laurent Guerby @ 1999-05-28 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > [...] > From reading the Rationale, I thought that the assignment to z would > result in a dispatching call to Get, using the tag of z that was set > at its initialization. What am I doing wrong here? How do controlling > return types work? A variable, once given an initial value, never change its type in Ada. So the assignment to a class wide variable can only be done in a declarative part. --LG ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-28 0:00 ` Laurent Guerby @ 1999-05-28 0:00 ` Richard D Riehle 1999-05-28 0:00 ` Tom Moran 0 siblings, 1 reply; 116+ messages in thread From: Richard D Riehle @ 1999-05-28 0:00 UTC (permalink / raw) In article <86lne9qh28.fsf@ppp-159-70.villette.club-internet.fr>, Laurent Guerby <guerby@acm.org> wrote: >Hyman Rosen <hymie@prolifics.com> writes: >> [...] >> From reading the Rationale, I thought that the assignment to z would >> result in a dispatching call to Get, using the tag of z that was set >> at its initialization. What am I doing wrong here? How do controlling >> return types work? > >A variable, once given an initial value, never change its type in >Ada. So the assignment to a class wide variable can only be done in a >declarative part. > >--LG Declarative parts can appear in subprograms or declare blocks. Therefore, one can take advantage of the ability to declare classwide variables in some interesting ways. Given a tagged type, type Machine is tagged ... with derviations, type Big_Machine is new Machine with ... type Solenoid is new Machine with ... type Tractor is new Big_Machine with ... one could dynamically dispatch to some operation overridden for each kind of machine such as, procedure Turn_On(M : in out Machine); If we also provide a classwide Get operation that retrieves objects of type Machine'Class from some kind of container, function Get (C : in Container) return Machine'Class; then we can have a loop that looks like this, loop declare M : Machine'Class := Get(container-name); -- constrains M with classwide Get function begin Turn_On(M); end; end loop; where the classwide variable will be constrained by the Get operation each time through the loop. This technique can be used in subprograms, tasks, or declare blocks. I have an example I use in some of my classes that demonstrates several variations on this for Stream_IO files. For Stream_IO you would want to use Machine'Class'Input(filename). It works quite nicely and is simple to implement and understand. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-28 0:00 ` Richard D Riehle @ 1999-05-28 0:00 ` Tom Moran 0 siblings, 0 replies; 116+ messages in thread From: Tom Moran @ 1999-05-28 0:00 UTC (permalink / raw) > M : Machine'Class := Get(container-name); We use that in Claw. For instance DIB : Claw.Bitmaps.Root_DIBitmap_Type'Class := Claw.Bitmaps.IO.Read("xxx.bmp"); so DIB can be a VGA_DIBitmap_Type or a Mono_DIBitmap_Type or whatever. Then writing, or putting it on the clipboard, or whatever, dispatches on the particular kind. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby @ 1999-05-28 0:00 ` Samuel Mize 1 sibling, 0 replies; 116+ messages in thread From: Samuel Mize @ 1999-05-28 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > Samuel Mize <smize@imagin.net> writes: >> I hope you find this of some interest. > > I'm trying to wrap my head around this class-wide type stuff. > I'm still at that stage of pre-clarity confusion :-) > > Here's some code I threw at gnat, based on Richard D. Riehle's example. ... > Gnat complains about the assignment to z: > ft.adb:8:14: ambiguous expression (cannot resolve "Get") > ft.adb:8:14: possible interpretation at ft.ads:12 > ft.adb:8:14: possible interpretation at ft.ads:9 > ft.adb:8:14: possible interpretation at ft.ads:6 I did a direct cut and paste to files on my system here and it worked fine. One of us must have an old version of GNAT. I'm using GNAT 3.10 on Windows. I can see an argument that, since a tag-indeterminate value is going into a class-wide type variable, the tag is not determined: > z: T'Class := GetC(a_f); ... > begin > z := Get(a_f); But, like you, I believe the code is correct. You can't have an uninitialized (tag undetermined) class-wide variable, so it ought to dispatch on that tag. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen ` (3 preceding siblings ...) 1999-05-27 0:00 ` Samuel Mize @ 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Jon S Anthony 4 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-27 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: >... object-oriented techniques > that were harder, or less elegant, in C++ than in Ada. I asked > for examples with the thought that perhaps the posters didn't know > C++ as well as they knew Ada, As an aside, with the background that I happen to have, I can more easily multiply examples of object-oriented methods that are not supported in either language. Since I know that C++ implements a specific method, and that Ada's facilities are more generally oriented, it has been easy for me to believe the assertions of others that they find the C++ model restrictive in some instances. Logic programming is a simple example. In at least one Actor-based method that I am aware of, a message is itself an object, and can, while it exists, send and recieve messages. This certainly doesn't fit in with the model of a "message" being a function (or procedure) call, which is basic to the object-oriented programming model of both C++ and Ada. Again, there are some AI-type object-oriented systems that generate new subclasses on the fly, altering their fields and giving them new methods. These are generally written in Lisp, where one can execute data. To do this in either C++ or Ada, one would have to write roughly the equivalent of a Lisp interpreter in the base language, and then really write most of the program in that new language. By the way, one other point about Ada's "object-oriented" syntax is that it supports non-object-oriented programming by extension. This allows one to write base code, then write new code that extends the functionality of the old code without recompiling the base code. You can do this in C++ with classes, but you don't have to design in a class-based model to do this in Ada. If you're interested, I discussed this in appalling detail earlier -- do a Deja News power search on the phrase "infinite case statement" in comp.lang.ada, and read my "shorter and new" posting on the subject. (It took me a couple of tries to explain it clearly.) Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-27 0:00 ` Samuel Mize @ 1999-05-27 0:00 ` Jon S Anthony 0 siblings, 0 replies; 116+ messages in thread From: Jon S Anthony @ 1999-05-27 0:00 UTC (permalink / raw) > > Hyman Rosen <hymie@prolifics.com> wrote: > >... object-oriented techniques ... > Again, there are some AI-type object-oriented systems that generate > new subclasses on the fly, altering their fields and giving them new > methods. Right. This sort of thing is easy in CLOS. What's more, if you use the MOP you can even change how dispatching behaves, etc. Of course, you also have true multiple dispatch as well. > These are generally written in Lisp, where one can execute > data. To do this in either C++ or Ada, one would have to write > roughly the equivalent of a Lisp interpreter in the base language, > and then really write most of the program in that new language. Right. Which is why we switched to Lisp (after trying both Ada and C++ <with Ada by far the better of those two>). What's more, since moder CommonLisp implementations come with optimizing _compilers_ built in and dynamically accessible, you'd have to write (or hook to) optimizing code generators as well. Otherwise, you'd be sucking wind in performance. You'd also have to write/aquire a GC and optimize it. Of course, if you go to this effort, you may as well bag the original application and become a Lisp vendor. > Sam Mize /Jon -- Jon Anthony Synquiry Technologies, Ltd. Belmont, MA 02478, 617.484.3383 "Nightmares - Ha! The way my life's been going lately, Who'd notice?" -- Londo Mollari ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Samuel Mize @ 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` David Botton 1999-05-27 0:00 ` Aidan Skinner 1999-05-28 0:00 ` Robert I. Eachus 1999-06-03 0:00 ` Matthew Heaney 3 siblings, 2 replies; 116+ messages in thread From: Richard D Riehle @ 1999-05-25 0:00 UTC (permalink / raw) In article <t7iu9hrqpw.fsf@calumny.jyacc.com>, Hyman Rosen <hymie@prolifics.com> wrote: >Once again, I will ask for an example demonstrating this, where >something is more complicated to use in C++ generics than in Ada. >This will make you the fourth person I have asked for this type >of example, the others being Richard D. Riehle, Samuel Mize, and >Robert Dewar. None of the others have chosen to post such an >example. I have a wonderful little proof that this is the case but this margin is too narrow for me to write it in its entirety. To paraphrase G.B. Shaw, "One an lay all the language advocates in the world end to end and still not reach a conclusion." There are certainly benefits to the C++ approach for generic programming, which is how Dr. Stroustrup refers to templates in his own book and how Ada refers to the same subject. There are also benefits to the Ada approach. There were inadequacies with the Ada model for generics before the addition of the "with package ..." construct. There were serious problems with C++ prior to adding the typename reserved word. Both languages are evolving. I prefer the Ada model for most designs. However, the syntax of C++ is a little more straightforward. The Ada syntax is designed to enforce a stricter set of type checking rules. C++ can also, in most but not all, cases do strict type checking. There are published examples of this. One of my favorite columns is in a magazine, C++ Report, called "Obfuscated C++." The monthly examples illustrate the central idea. Take any of the examples from that column and try to create equally obfuscated Ada. In fact, try to create an "obfuscated" Ada program. Pretty difficult (not impossible). I am not going to engage in dueling source code where anything I can play on my banjo you can play your guitar and Robert can play on his pipe organ. On the other hand, Tocatta and Fuge in D Minor is a bit of a stretch for my banjo and Foggy Mountain Breakdown sounds a little strange on the pipe organ. C++ is a great language for graphics and other stuff that is not safety-critical. It would seem to me, strange, to select it as the language for flight avionics, air traffic control, or other projects where human life is at stake. I know people do this, but knowing a little bit about both Ada and C++, I find it scary when someone decides to use C++ in this situation. On the other hand, for high-speed graphics where safety is not a factor, C++ might ] often be a better choice than Ada. Some instruments just do better for certain kinds of music. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Richard D Riehle @ 1999-05-25 0:00 ` David Botton 1999-05-26 0:00 ` Tom Moran 1999-05-27 0:00 ` Aidan Skinner 1 sibling, 1 reply; 116+ messages in thread From: David Botton @ 1999-05-25 0:00 UTC (permalink / raw) I don't find that the case at all and I don't think other here would either. See: For an example of a freeware Ada 3D engine see Gautier's page: http://members.xoom.com/gdemont/e3d.htm I have already been playing around with Direct x and Direct 3D using my COM binding generator and I have seen some fantastic simulations done in Ada. The Ada support for tasking and protected objects is exactly what makes high speed complex graphics a great fit. Beyond that the very keen ability to do concrete representations make it a very complete package. What in C++ lends its self towards better graphics support? David Botton Richard D Riehle wrote: > On the other hand, > for high-speed graphics where safety is not a factor, C++ might ] > often be a better choice than Ada. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` David Botton @ 1999-05-26 0:00 ` Tom Moran 0 siblings, 0 replies; 116+ messages in thread From: Tom Moran @ 1999-05-26 0:00 UTC (permalink / raw) >The Ada support for tasking and protected objects is exactly what makes >high speed complex graphics a great fit. Definitely. My first real Ada project involved video capture/edit/playback and it was easy with separate video/audio/user interaction tasks. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` David Botton @ 1999-05-27 0:00 ` Aidan Skinner 1 sibling, 0 replies; 116+ messages in thread From: Aidan Skinner @ 1999-05-27 0:00 UTC (permalink / raw) On Tue, 25 May 1999 20:04:20 GMT, Richard D Riehle <laoXhai@ix.netcom.com> wrote: > on his pipe organ. On the other hand, Tocatta and Fuge in D Minor > is a bit of a stretch for my banjo and Foggy Mountain Breakdown > sounds a little strange on the pipe organ. Ah, but have you heard my post-modern neoclassical avant garde desconstructionist version of "Smoke On The Water" on trash can and hose pipe? ;) - Aidan -- http://www.skinner.demon.co.uk/aidan/ Real men whistle ed commands at 300 baud into a can. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Richard D Riehle @ 1999-05-28 0:00 ` Robert I. Eachus 1999-05-28 0:00 ` Brian Rogoff 1999-05-29 0:00 ` Ehud Lamm 1999-06-03 0:00 ` Matthew Heaney 3 siblings, 2 replies; 116+ messages in thread From: Robert I. Eachus @ 1999-05-28 0:00 UTC (permalink / raw) To: Hyman Rosen Hyman Rosen wrote: > > 2) It therefore CANNOT be made virtual so you can't dispatch on it. > > So you mean in Ada, I can write a dot(a,b) which will dispatch on > either a or b? I wasn't aware that this was the case. Technically you can't, but in practice you can. Ada allows both classwide and dispatching parameters. Multiple dispatching is done by having a visible operation which is classwide for one or more parameters, then sorting out the cases and dispatching on the second parameter. Huh? Maybe this does take an example. Let's say that we need a matrix package that allows multiple representations of matrices. Some specialized to save storage such as identity matrices, tridiagonal matrices, etc. and some representations which simplify further operations while representing arbtrary matrices: scaled matrices, LUP decomposition, basis representation, etc. In Ada, I create a package which provides the basic operations of the type: with Ada.Finalization; package Matrices is type Matrix(X,Y: Integer := 0) is abstract tagged private; -- X and Y provide the bounds, the defualt value is to allow different -- sized values to be assigned to objects. function Create_Zero_Matrix (X,Y: Integer) return Matrix; procedure Set_Element(M: in out Matrix; X,Y: in Integer; To: Float); function "*" (L,R: Matrix'Class) return Matrix'Class; function "+" (L,R: Matrix'Class) return Matrix'Class; function "-" (L,R: Matrix'Class) return Matrix'Class; -- etc... private ... type Matrix(X,Y: Integer := 0) is new Ada.Finalization.Controlled with null record; -- No data in abstract base type. function Multiply1(L: Matrix; R: Matrix'Class) return Matrix'Class; function Multiply2(L,R: Matrix) return Matrix'Class; function To_Standard_Rep(From: Matrix) return Matrix'Class; -- etc... end Matrices; -- Now we need some Child packages that declare the various actual -- representation. Let's start with the unrestricted standard -- representation. package Matrices.Standard is type Standard_Matrix is new Matrices.Matrix with private; private procedure Adjust(Object: in out Standard_Matrix); procedure Finalize(Object: in out Standard_Matrix); -- overrides for the Controlled operations. type Data_Array is array (Integer range <>, Integer range <>) of Float; type Data_Pointer is access all Data; type Standard_Matrix is new Matrices.Matrix with record Data: Data_Pointer := new Data_Array'(1..X =>(1..Y => 0.0)); end record; function Multiply1(L: Standard_Matrix; R: Matrix'Class) return Matrix'Class; function Multiply2(L,R: Standard_Matrix) return Matrix'Class; function ToStandard_Rep(From: Matrix) return Matrix'Class; end Matrices.Standard; -- Let's have at least two children... package Matrices.Identity is type Identity_Matrix is new Matrices.Matrix with private; function Create_Identity_Matrix (Size: Integer) return Identity_Matrix; function Create_Zero_Matrix (Size: Integer) return Identity_Matrix; private procedure Initialize(Object: in out Identity_Matrix); -- Since there is no data we don't need a Adjust and Finalize, -- but I want to check that X = Y in Initialize. type Identity_Matrix is new Matrices.Matrix with null record; function Multiply1(L: Identity_Matrix; R: Matrix'Class) return Matrix'Class; function Multiply2(L,R: Identity_Matrix) return Matrix'Class; function To_Standard_Rep(From: Identity_Matrix) return Matrix'Class; ... end Matrices.Identity; -- might as well do the body for this one... with Matrices.Standard; package body Matrices.Identity is function Create_Identity_Matrix return Identity_Matrix is Result: Identity_Matrix(X,Y); begin return Result; end Create_Identity_Matrix; function Initialize(Object: in out Identity_Matrix) is begin if X /= Y then raise Constraint_Error; end Initialize; function Multipy1(L: Identity_Matrix; R: Matrix'Class) return Matrix'Class is begin return R; end Multiply1; function Multiply2(L,R: Identity_Matrix) return Matrix'Class is begin return R; end Multiply2; function To_Standard_Rep(From: Identity_Matrix) return Matrix'Class is Result: Matrices.Standard.Standard_Matrix(From.X,From.Y); begin -- counts on the Standard_Matrix being intialized to all zeros. for I in 1..From.X loop Result.Data(I,I) := 1.0; end loop; return Result; end To_Standard_Rep; end Matrices.Identity; -- okay now part of the parent package body. package body Matrices is ... function "*"(L,R: Matrix'Class) return Matrix'Class is begin if L.Y /= R.X raise Constraint_Error; end if; -- might as well do this in the classwide operation, since it is -- independent of representation. if L'Tag = R'Tag then return Multiply2(L,R); else return Multiply1(L,R); end if; end "*"; ... end Matrices; If this were a real implementation, I would probably make some of the operations in Matrices explicitly abstract, and have more classwide conversion functions such as to an LUP decomposition. And of course, in a real implementation the body of "*" would be much more complex, preferring to call the Identity_Matrix operation even when the identity matrix or tridiagonal matrix is the right parameter as well, etc. But the genenral idiom requires a minimum of one private dispatching operation for each public classwide operation, which is very little overhead compared to single dispatching. Also note that this is really double dispatching, but if you wanted to declare "*" as: function "*"(L,R: Matrix'Class) return Matrix; The you would be doing triple dispatching, with the first dispatch on the return type, without much more implementation effort. Such a package might be useful if most of your matrices were in either LUP or basis form. > I actually > think that this is in fact *not* the case, in which case I have no > trouble writing a dispatching version in C++ either - just have > dot(a,b) call a.dot(b). In both Ada and C++, the apparent external > symmetry will then hide the internal asymmetry. As you point out it is not impossible to do that in C++ as well. But notice Multiply2, which dispatches on both L and R, or for that matter "*" doesn't dispatch on anything externally, even though it effectively double dispatches. (The difference is that in Multiply2 both parameters must be of the same type (subclass), while in "*" they need not be types that know of each other. One of the cute things you can do with a complex dispatching case, is put an error handler on "*" like so: function "*"(L,R: Matrix'Class) return Matrix'Class is begin if L.Y /= R.X raise Constraint_Error; end if; -- might as well do this in the classwide operation, since it is -- independent of representation. begin if L'Tag = R'Tag then return Multiply2(L,R); elsif ... else return Multiply1(L,R); end if; exception when Constraint_Error => return Multipy2(To_Standard_Rep(L),To_Standard_Rep(R)); end; end "*"; Of course more likely is to recognize the unanticipated cases in the various Multiply1 functions with: else return Multiply1(L,To_Standard_Rep(R)); (You don't have to do this as a recursive call, but it works cleanly, and doesn't take much code for these presumably rare or unanticipated cases.) > Once again, I will ask for an example demonstrating this, where > something is more complicated to use in C++ generics than in Ada. > This will make you the fourth person I have asked for this type > of example, the others being Richard D. Riehle, Samuel Mize, and > Robert Dewar. None of the others have chosen to post such an > example. I've done one example (probably with a few typos and thinkos since it is Friday afternoon), I'm not going to do this one too. The reason no one is anxious to demonstrate this is that reasonable examples take several pages of code in Ada, and of course lots more in C++. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-28 0:00 ` Robert I. Eachus @ 1999-05-28 0:00 ` Brian Rogoff 1999-05-29 0:00 ` Ehud Lamm 1 sibling, 0 replies; 116+ messages in thread From: Brian Rogoff @ 1999-05-28 0:00 UTC (permalink / raw) On Fri, 28 May 1999, Robert I. Eachus wrote: > Hyman Rosen wrote: > > Once again, I will ask for an example demonstrating this, where > > something is more complicated to use in C++ generics than in Ada. > > This will make you the fourth person I have asked for this type > > of example, the others being Richard D. Riehle, Samuel Mize, and > > Robert Dewar. None of the others have chosen to post such an > > example. > > I've done one example (probably with a few typos and thinkos since > it is Friday afternoon), I'm not going to do this one too. The reason > no one is anxious to demonstrate this is that reasonable examples take > several pages of code in Ada, and of course lots more in C++. I think that there are a few examples of reasonably short length, going in each direction (Ada > C++ and C++ > Ada). I thought one of the original preconditions was OO, but if its just generics, then the example Richard O'Keefe presented a few years ago during one of the downward closure discussions where he used Ada generics to simulate downward closures is probably a good "pro-Ada" one, though I think the intent of the original example was to show how bad Ada came off against Pascal and Scheme. Note that using generics this way doesn't even really do a good job compared to what you could do with downward closures; your Integrate_2D wouldn't have to be tied to a particular Integrate_1D, you could just pass it in as an argument. Any nice way around that problem, besides using GNAT specific features? Anyways, I don't think this translates easily to C++, but if Hyman or someone else can surprise me I'd be delighted. -- First we write a simple 1-D integrator using the trapezoid rule generic type Float_Type is digits; with function F(X : Float_Type) return Float_Type; function Integrate_1D(Lower, Upper: Float_Type; Steps : Positive) return Float_Type; -- Tail recursive trapezoid rule, a tip o' the hat to Schemers! function Integrate_1D(L1, U1: Float_Type; Steps : Positive) return Float_Type is Dx : constant Float_Type := (Upper - Lower) / Float_Type(Steps); function Iterate( Step : Positive; Value : Float_Type ) return Float_Type is begin if Step = Steps then return DX * Current_Value; else return Iterate( Step + 1, Value + F(Lower + Float_Type(Step) * Dx)); end if; end Iterate; begin Iterate(1, .5 * F(Lower) + F(Upper)); end; -- The 2-D integration spec generic with function F(X, Y : Float_Type) return Float_Type; function Integrate_2D(L1, U1, L2, U2: Float_Type; S1, S2 : Positive) return Float_Type; -- How I wish Ada 95 had real downward closures!!! function Integrate_2D(L1, U1, L2, U2: Float_Type) return Float_Type is function Outer_Integrand(Y: Float_Type) return Float_Type is function Inner_Integrand(X: Float_Type) return Float_Type is begin return F(X, Y); end Inner_Integrand; function Inner_Integrator is new Integrate_1D(F => Inner_Integrand, Steps => S1); begin return Inner_Integrator(L1, U1); end Outer_Integrand; function Outer_Integrator is new Integrate_1D(F => Outer_Integrand, Steps => S2); begin return Outer_Integrator(L2, U2); end Integrate_2D; -- Brian ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-28 0:00 ` Robert I. Eachus 1999-05-28 0:00 ` Brian Rogoff @ 1999-05-29 0:00 ` Ehud Lamm 1999-05-30 0:00 ` chris 1999-06-03 0:00 ` Matthew Heaney 1 sibling, 2 replies; 116+ messages in thread From: Ehud Lamm @ 1999-05-29 0:00 UTC (permalink / raw) About double dispatching using class-wide paramters and run typme type identifaction using 'tag: I had a feeling this is what you are thinking about, since Ada like the other languages I am familiar with doesn't go for double dispatching - nad rightly so (try to define consistent semantics for such a thing). However using 'tag or other methods of RTTI (as are avaible in C++) is usually concidred un-OOP, and not totally without reason. The argument is that if you do manual checks for tags, you must change the code base when you inherit, as opposed to simply coding new and sperate routines for the overridden and new features of the new type. This is one of the problems OOP tries to solve (you can see this discussed in many OOP books). Some OOP gurus even take the extreme view that almost any if/case statements in a program indicate that the inheritance tree should be exapnded. Ehud Lamm mslamm@pluto.mscc.huji.ac.il ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-29 0:00 ` Ehud Lamm @ 1999-05-30 0:00 ` chris 1999-05-30 0:00 ` Harry George ` (3 more replies) 1999-06-03 0:00 ` Matthew Heaney 1 sibling, 4 replies; 116+ messages in thread From: chris @ 1999-05-30 0:00 UTC (permalink / raw) Today I saw a book on modula-3. I think Ada OO should have been designed as modula-3 OO is. In Modula-3, you have a modula, which is same as an Ada package. but also, you have what is called an OBJECT, (which looked like a RECORD), which contains DATA part, and METHODS part. Inside a modula, you can declare an OBJECT. So, here we have a language, which I thought was very similar to Ada, but used the familiar class like construct for the OO type. I have no idea why Ada did not do it the same way. I wonder if when Ada95 OO was designed, if modula-3 was around? I liked the way modula-3 did it. I think I am going to learn more about that language. Too bad it is not a very much used language. chris. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` chris @ 1999-05-30 0:00 ` Harry George 1999-05-30 0:00 ` Vladimir Olensky 1999-05-30 0:00 ` Robert Dewar ` (2 subsequent siblings) 3 siblings, 1 reply; 116+ messages in thread From: Harry George @ 1999-05-30 0:00 UTC (permalink / raw) chris@nospam writes: > Today I saw a book on modula-3. > > I think Ada OO should have been designed as modula-3 OO is. > [snip] > > I have no idea why Ada did not do it the same way. I wonder if when > Ada95 OO was designed, if modula-3 was around? > From the home page (http://www.research.digital.com/SRC/modula-3/html/home.html): "Designed in the late 1980s at Digital Equipment Corporation and Olivetti" > I liked the way modula-3 did it. I think I am going to learn more > about that language. Too bad it is not a very much used language. Amen. A small but experienced community still uses it whereever possible. OO is just one of the things M3 does right. We can only hope Java steps up to UNSAFE and non-OO gc'd and non-gc'd structures. > > chris. > > -- Harry George hgg9140@seanet.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` Harry George @ 1999-05-30 0:00 ` Vladimir Olensky 1999-05-31 0:00 ` Robert Dewar 0 siblings, 1 reply; 116+ messages in thread From: Vladimir Olensky @ 1999-05-30 0:00 UTC (permalink / raw) Harry George wrote in message ... >chris@nospam writes: >> I have no idea why Ada did not do it the same way. I wonder if when >> Ada95 OO was designed, if modula-3 was around? >> >From the home page (http://www.research.digital.com/SRC/modula-3/html/home.html): > "Designed in the late 1980s at Digital > Equipment Corporation and Olivetti" > >> I liked the way modula-3 did it. I think I am going to learn more >> about that language. Too bad it is not a very much used language. > >Amen. A small but experienced community still uses it whereever >possible. OO is just one of the things M3 does right. We can only >hope Java steps up to UNSAFE and non-OO gc'd and non-gc'd structures. M3 language definition was published in August 1988 and implemented soon after that . In January 1989 some revisions were made to the language to reflect the experience of the M3 implementation. So M3 is at least 6 years older than Ada 95. M3 runs almost on all platforms (as Ada now). For me use of UNSAFE modules is very good approach to provide program reliability. Probably better than imposing restriction everywhere as in Ada. The same concept could be used in Ada 95 to relax restrictions where needed. In M3 you are not allowed to do unsafe operations in usual modules (so it is very restrictive there, in some cases much more restrictive than Ada) but in UNSAFE modules you can do whatever you need. Isolating unsafe operations in UNSAFE modules provide very good control over them. Using OPAQUE types you can build safe interfaces to unsafe modules. Another remarkable feature of M3 is that it has Garbage Collector as part of the language specification. (Long before Java). GB implementation was successful and may be used as a good example. If you don't want to use GB any object you may declare it as UNTRACED. Several years ago developers of M3 founded company CMASS (www.cmass.com) to build commercial version of M3 and did some very impressive things (namely Reactor - see below). Unfortunately their efforts did not bring desired results due to different factors. Their story is a good lesson for others as well. One of them is that at some moment they took wrong direction putting all their efforts for building JVM using M3 that should work on every known platform. They did that but priced it about $10000. So no wonder that they could not compete with some known big companies that did that for no money for customer so time and resources were lost. The other thing was that they thought that M3 is the best programming language in the world (and it really was for very long period of time) with fully functional Garbage Collector and only this is enough to win (the same as some people think regarding Ada now). Another thing that had impact on M3 destiny was that for very, very long period of time it was experimental language for closed community ( DEC SRC and some other research centers)without no attempts to build and sell commercial versions of M3. Any closed community in our world will shrink eventually if it do not make efforts to expand. As pressure from outside is almost always increasing then pressure from inside should be adequate not to loose living area. This is universal law. Earth history has illustrated this many times. As time goes new more perfect creatures come to existence that are pushing away older ones. But some lives forever without no changes (sharks, snakes, crocodiles). Please note that these are creatures that are eating other creatures. Hope that Ada will live long as sharks. One this in which CMASS M3 is still ahead of time is it's team development system "Reactor". It has central development server and any developer can do his/her work from any workstation with WEB browser. Very impressive. In many respects Ada and M3 is very very close to each other. As Ada 95 was born later so it has some other features that M3 does not have (e.g. child packages). Ada 95 is a logical step for people who used M2 and M3 before. By the way Averstar supports and sells extended version of Modula-2 called Modula-GM that is used by General Motors for car engine controllers. A lot of people that use Ada do not even know that they use Modula-GM as well. Regards, Vladimir Olensky ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` Vladimir Olensky @ 1999-05-31 0:00 ` Robert Dewar 0 siblings, 0 replies; 116+ messages in thread From: Robert Dewar @ 1999-05-31 0:00 UTC (permalink / raw) In article <928093666.328.83@news.remarQ.com>, "Vladimir Olensky" <vladimir_olensky@yahoo.com> wrote: > Another remarkable feature of M3 is that it has Garbage > Collector as part of the language specification. > (Long before Java). Yes, it is surprising that some folks think Java was the first strongly typed procedural language to require garbage collection when M3 had appeared nearly ten years before .... Almost as surprising as the fact that some folks thinking M3 was the first strongly typed procedural language to require garbage collection when Algol-68 had appeared nearly 20 years earlier :-) And it is certainly fair to compare Algol-68 with Modula-3. Actually A68 was really significantly more successful than Modula-3. Two major manufacturers had fully supported Algol-68 compilers, and Algol-68 was very widely taught in England at one stage (in the 1970 British Journal of Computing survey, it was most mentioned as the ideal teaching language by British respondents -- reflecting the availability of the excellent ICL compiler). Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` chris 1999-05-30 0:00 ` Harry George @ 1999-05-30 0:00 ` Robert Dewar 1999-05-31 0:00 ` Vladimir Olensky 1999-06-01 0:00 ` Richard D Riehle 3 siblings, 0 replies; 116+ messages in thread From: Robert Dewar @ 1999-05-30 0:00 UTC (permalink / raw) In article <7ircia$ued@drn.newsguy.com>, chris@nospam wrote: > Today I saw a book on modula-3. > > I think Ada OO should have been designed as modula-3 OO is. > > So, here we have a language, which I thought was very similar > to Ada, but used the familiar class like construct for the OO > type. > I have no idea why Ada did not do it the same way. I wonder if > when Ada95 OO was designed, if modula-3 was around? Yes, of course it was. The thing to realize is that the design of Ada 95 is the way it is not because someone didn't think of something, but on the contrary because a lot of people thought a whole lot. The key point in Ada is to provide orthogonal features that can be used for many purposes. Some of these features are modularity, information hiding, procedural abstraction, type extension, inheritance and dynamic dispatching. Yes, it is possible (and convenient) to use these for various object oriented paradigms, but they are more general than this, and are designed to be convenient to use in more general circumstances. For instance, take the example I mentioned, if you define an algebra of operations on elements with operations such as addition, then it makes good sense to use the notions of tagged types, extensible types, inheritance and dynamic dispatching to provide a definition that can be extended, e.g. a more complex algebra can be developed which adds a multiplication operation. Now all this is expressible very nicely in Ada (I leave it as an easy, though not trivial, excercise to write the code), but it really does not make any sense to think of addition as a method which sends messages to the elements thought of as objects. This is a forced viewpoint that might have to be used in other languages, but definition will not be helpful in modeling an algebra, where the notion is a functional one, rather than a procedural one with objects. Note that in this case, the elements have no state, they are just values. Indeed you can take an entirely applicative view of this construction in Ada without the slighest sense of procedural thinking. Given that the notion of object is all about state and sending messages that interact with this state, objects are really quite inappropriate for this particular application. In particular, this example cannot be programmed nearly as neatly in Modula-3. Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` chris 1999-05-30 0:00 ` Harry George 1999-05-30 0:00 ` Robert Dewar @ 1999-05-31 0:00 ` Vladimir Olensky 1999-06-03 0:00 ` Dale Stanbrough 1999-06-01 0:00 ` Richard D Riehle 3 siblings, 1 reply; 116+ messages in thread From: Vladimir Olensky @ 1999-05-31 0:00 UTC (permalink / raw) chris@nospam wrote in message <7ircia$ued@drn.newsguy.com>... > >In Modula-3, you have a modula, which is same as an Ada package. >but also, you have what is called an OBJECT, (which looked >like a RECORD), which contains DATA part, and METHODS part. > >Inside a modula, you can declare an OBJECT. > >So, here we have a language, which I thought was very similar to >Ada, but used the familiar class like construct for the OO type. ============================================== As a matter of fact M3 allows you to use both ways to invoke methods on objects if my nemory serves me right. ---------------------------------------------------------------------------- ------ -- Object.method and method (object) are both valid calls for M3. ---------------------------------------------------------------------------- ------ It just depends on the intention of the Interface Module designer who allows you to use one of them or both (first one in most cases). Usually implementation modules use the method (object) syntax but it is hidden from the user (as the implementation is not visible to customer). As M3 allows to have several different interfaces to the same implementation module (exploiting so called partial revelation) so it is possible to have two sets of operation (with different syntax) to be in the different interfaces to given implementation as well. M3 is extremely flexible regarding this. Moreover, depending on how you defined your object methods you may even allow user to redefine object methods during program execution (just changing procedure address in VMT). (e.g.during execution you can create array of bytes representing some chain of assembler instructions and then call it when needed). It is just an example, more safe is to have object method which can call any other procedure with the given profile. If anyone have a look at M3 sources he/she can find there a lot of extremely interesting things. May be M3 experience will be considered seriously some time in the future. I wonder why Averstar sells and supports only Ada 95 and Modula-GM. It would be logical to have M3 in the list of it's products . It would be very impressive set: Ada 95, . AppletMagic, Modula-3, Modula-GM. Regards, Vladimir Olensky Here some code from M3 sources as an illustration: ------------------------------------- INTERFACE GO; EXCEPTION PropUndefined; EXCEPTION StackError; TYPE Shape = {Complex, NonConvex, Convex, Unknown}; TYPE T <: Public; Public = ProxiedObj.T OBJECT METHODS init () : T; <stripped code> setName (name : TEXT); getName () : TEXT; <stripped code> pushMouseCB (cb : MouseCB.T); popMouseCB () RAISES {StackError}; <stripped code> END; ---------------------------------------------------------------------------- ---- Copyright (C) 1994, Digital Equipment Corp. Created by Marc Najork MODULE GO EXPORTS GO, GOPrivate; <stripped code> REVEAL T = Private BRANDED OBJECT OVERRIDES init := Init; <stripped code> setName := SetName; getName := GetName; pushMouseCB := PushMouseCB; popMouseCB := PopMouseCB; <stripped code> END; PROCEDURE Init (self : T) : T = BEGIN self.props := NIL; self.damaged := TRUE; self.name := NIL; self.dl := 0; self.mouseCBstack := NEW (MouseCBStack.T).init (); self.positionCBstack := NEW (PositionCBStack.T).init (); self.keyCBstack := NEW (KeyCBStack.T).init (); RETURN self; END Init; PROCEDURE SetName (self : T; name : TEXT) = BEGIN self.name := name; END SetName; PROCEDURE GetName (self : T) : TEXT = BEGIN RETURN self.name; END GetName; <stripped code> PROCEDURE PushMouseCB (self : T; cb : MouseCB.T) = BEGIN self.mouseCBstack.push (cb); END PushMouseCB; PROCEDURE PopMouseCB (self : T) RAISES {StackError} = BEGIN self.mouseCBstack.pop (); END PopMouseCB; <stripped code> BEGIN Transform := NEW (Transform_PN).init (Matrix4.Id); END GO. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-31 0:00 ` Vladimir Olensky @ 1999-06-03 0:00 ` Dale Stanbrough 1999-06-02 0:00 ` mike 0 siblings, 1 reply; 116+ messages in thread From: Dale Stanbrough @ 1999-06-03 0:00 UTC (permalink / raw) Vladimir Olensky wrote: [some sample Modula-3 code] I just remembered on seeing the code that Modula-3 requires reserved words to be in upper case. This would surely make Mike Feldman happy! :-) Dale ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-03 0:00 ` Dale Stanbrough @ 1999-06-02 0:00 ` mike 1999-06-03 0:00 ` Robert Dewar 0 siblings, 1 reply; 116+ messages in thread From: mike @ 1999-06-02 0:00 UTC (permalink / raw) In article <dale-0306991131040001@dale.cs.rmit.edu.au>, dale@cs.rmit.edu.au says... > >Vladimir Olensky wrote: > >[some sample Modula-3 code] > > >I just remembered on seeing the code that Modula-3 requires >reserved words to be in upper case. This would surely make >Mike Feldman happy! :-) > > I setup my emacs Ada mode so that it makes keywords upper case also :) I always found it easier to read code like that. I even used to have a header file for my C/C++ code that does: #define WHILE while #define DO do #define BEGIN { #define END } #define FOR for #define IF if #define ELSE else etc.. which made my C/C++ more pleasent for me to work one, and more readable. Mike ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-02 0:00 ` mike @ 1999-06-03 0:00 ` Robert Dewar 1999-06-06 0:00 ` David Botton 0 siblings, 1 reply; 116+ messages in thread From: Robert Dewar @ 1999-06-03 0:00 UTC (permalink / raw) In article <7j4nro$1ft@drn.newsguy.com>, mike@nospam wrote: > which made my C/C++ more pleasent for me to work one, and more > readable. > This kind of thing is VERY bad style. One of the primary things that you should consider in writing code is to make it pleasant for OTHERS to work on and read. Adopting non-standard idiosyncratic styles (your C/C++ example, if not intended as a joke, is an extreme example), is in the worst tradition of deliberate code obfuscation. Conformity to both formal and informal standards in programming is an important part of good style. Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-03 0:00 ` Robert Dewar @ 1999-06-06 0:00 ` David Botton 1999-06-07 0:00 ` Robert Dewar 0 siblings, 1 reply; 116+ messages in thread From: David Botton @ 1999-06-06 0:00 UTC (permalink / raw) Yes, but possibly his project standardized on this alternate representation. Then this would be conformity, good style and readable :) David Botton Robert Dewar wrote: > > In article <7j4nro$1ft@drn.newsguy.com>, > mike@nospam wrote: > > which made my C/C++ more pleasent for me to work one, and more > > readable. > > > > This kind of thing is VERY bad style. One of the primary > things that you should consider in writing code is to make > it pleasant for OTHERS to work on and read. Adopting > non-standard idiosyncratic styles (your C/C++ example, if > not intended as a joke, is an extreme example), is in the > worst tradition of deliberate code obfuscation. > > Conformity to both formal and informal standards in programming > is an important part of good style. > > Sent via Deja.com http://www.deja.com/ > Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-06 0:00 ` David Botton @ 1999-06-07 0:00 ` Robert Dewar 0 siblings, 0 replies; 116+ messages in thread From: Robert Dewar @ 1999-06-07 0:00 UTC (permalink / raw) In article <375A8197.5DAB7C57@Botton.com>, David Botton <David@Botton.com> wrote: > Yes, but possibly his project standardized on this alternate > representation. Then this would be conformity, good style and readable > :) Well I know there is a smiley here, but just so there is no confusion in my thinking, a project that standardized on such a NON-standard way of doing things would me making a very serious mistake. One of the important tasks of any project is to try to make sure that your code is written in a way that people generally familiar with your technology will be able to easily understand and maintain. For example, I consider the important thing about the GNAT code not that people in the GNAT project find it easy to read here at ACT, but that all sorts of people OUTSIDE the GNAT project have commented that it was easy to read. If we used some kind of bizarre non-standard way of doing things (say upper case keywords and text indented in the opposite direction from usual, and semicolons at the beginning of each line instead at the end), I don't think we would get this reaction. PROCEDURE horrible is x : integer ;y : integer ;BEGIN NULL ;END ; (even if we followed this style rigourously :-) Using Pascal style keywords in C programs is almost as bad a transgression of normal coding standards in C! Sent via Deja.com http://www.deja.com/ Share what you know. Learn what you don't. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-30 0:00 ` chris ` (2 preceding siblings ...) 1999-05-31 0:00 ` Vladimir Olensky @ 1999-06-01 0:00 ` Richard D Riehle 3 siblings, 0 replies; 116+ messages in thread From: Richard D Riehle @ 1999-06-01 0:00 UTC (permalink / raw) In article <7ircia$ued@drn.newsguy.com>, chris@nospam wrote: >Today I saw a book on modula-3. > >I think Ada OO should have been designed as modula-3 OO is. Modula-3 has some interesting ideas that could contribute to future versions of Ada. However, Modula-3, in its effort to keep the language simple, falls a little short of the strong typing we expect of a well-designed Ada 95 program. >In Modula-3, you have a modula, which is same as an Ada package. Well, actually, not the same. There are some significant differences. Ada has a private part for the equivalent of an INTERFACE, and that increases the flexibility of the type model in terms of separate compilation of components of an implementation. One may reasonably criticize this feature as being excessively complex, but it does increase one's options in developing software with Ada. On the other hand, those added options do make the development of compilers more complex. The trade-off between compiler complexity and application programmer options raises issues that will not be easily agreed upon. >but also, you have what is called an OBJECT, (which looked >like a RECORD), which contains DATA part, and METHODS part. While the Modula-3 approach to this is a little safer than the equivalent in C++, it still has weaknesses. For example, if I understand correctly, there are still cases in which the compiler cannot determine if certain kinds of assignments are correct, and these can cause run-time faults. >Inside a modula, you can declare an OBJECT. > >So, here we have a language, which I thought was very similar to >Ada, but used the familiar class like construct for the OO type. Once again, we are seduced by the apparent simplicity of the type <=> module <=> class (OBJECT) On the surface, this simplicity is attractive. In practice, it leads to greater complexity than one might have expected. This is certainly the case in C++. Although I have not written Modula-3 programs, my reading of the language description makes me suspect that some of the same problems from C++ will manifest themselves. >I have no idea why Ada did not do it the same way. I wonder if when >Ada95 OO was designed, if modula-3 was around? The designers of Ada 95 knew about Modula-3. The philosophy of the two languages is different. Those who favor Modula-3 (I know some of them) tend to believe Ada is too full of features and favor a smaller language definition. For example, one author says "The rules associated with Ada generics are too complicated for our taste." However, it is that set of rules that helps give Ada is unparalleled power in designing compile-time checked, generic reusable components. >I liked the way modula-3 did it. I think I am going to learn more >about that language. Too bad it is not a very much used language. Please do learn Modula-3 as thoroughly as possible. Then return to your assessment of Ada 95. You may find yourself more charitable toward Ada. The design of Ada was not a process of overlooking other language designs. It included careful analysis of what other languages had to offer. In fact, this one of the benefits of Ada 95 following the design of other languages. The architects and reviewers of Ada 95 had the opportunity to evaluate how well certain features worked in other languages and the option to incorporate those that seemed appropriate into the Ada language design. The decision to design Ada 95 as it is designed was a deliberate choice, for well-taken technical reasons. One may disagree with those technical reasons, but they are as valid, in the end, as other choices that might have been made. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-29 0:00 ` Ehud Lamm 1999-05-30 0:00 ` chris @ 1999-06-03 0:00 ` Matthew Heaney 1 sibling, 0 replies; 116+ messages in thread From: Matthew Heaney @ 1999-06-03 0:00 UTC (permalink / raw) Ehud Lamm <mslamm@mscc.huji.ac.il> writes: > However using 'tag or other methods of RTTI (as are avaible in C++) is > usually concidred un-OOP, and not totally without reason. The argument > is that if you do manual checks for tags, you must change the code > base when you inherit, as opposed to simply coding new and sperate > routines for the overridden and new features of the new type. Not necessarily. It may be the case the you're using 'Tag simply to make sure the tags are the same. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen ` (2 preceding siblings ...) 1999-05-28 0:00 ` Robert I. Eachus @ 1999-06-03 0:00 ` Matthew Heaney 3 siblings, 0 replies; 116+ messages in thread From: Matthew Heaney @ 1999-06-03 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > So you mean in Ada, I can write a dot(a,b) which will dispatch on > either a or b? Yes, if A and B have the same specific type. <types AT and BT derive from T> A1, A2 : AT; B1, B2 : BT; AC1, AC2 : T'Class := <object has type AT>; BC1, BC2 : T'Class := <object has type BT>; begin .. := Dot (A, B); -- illegal, detected at compile-time Dot (A1, A2); -- legal Dot (B1, B2); -- legal Dot (AC1, AC2); -- legal, tags compared at run-time Dot (BC1, BC2); -- legal, tags compared at run-time Dot (AC1, BC1); -- legal, but run-time tag check fails, -- and Constraint_Error is raised end; ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Robert Dewar @ 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Hyman Rosen 1999-06-03 0:00 ` Matthew Heaney 2 siblings, 1 reply; 116+ messages in thread From: Samuel Mize @ 1999-05-25 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> wrote: > Samuel Mize <smize@imagin.net> writes: >> There are other OO design approaches that are harder to implement in >> C++ than in Ada, because C++ strongly supports one specific view of >> object-oriented technology. > > Could you give an example of this? I confess that I can't just pop up an example. My non-C++ and non-Ada object-oriented systems was (good grief) over a decade ago, and I'm not all the way up the learning curve in C++. Let me try to get someone else involved who will (I think) be able to give you a better answer, ask you a question, and give you a "reasonable" argument to consider. I grant that this is weak. THE SOMEONE ELSE is a frequent poster here, but I don't want to drag him into a thread if he's intentionally ignoring it. I'll email him a copy of this posting. He has said that he does object-oriented development, but that he does not prefer the C++ model. I have to assume he routinely does things that don't fit well into that model. I hope he will discuss (or give a pointer to previous discussion) what method he prefers, and why it is incompatible with C++. THE QUESTION: how does one do "mix-in" classes in C++? I'd bet a nickel that you can, but I don't know the specific mechanism. The "mix-in" metaphor is described in the Ada 95 Rationale, 4.6.2. THE "REASONABLE" ARGUMENT: C++ supports a very specific view of object-oriented development. I'll list several things that I believe are true about C++ (feel free to correct errors). Each of them represents a methodology decision. Perfectly good methods can be derived where each or all of these is false. In that case, C++ would not support that method well. - The class is the primary form of data encapsulation. (I have seen C++ advocates argue that Ada is weak because it provides encapsulation outside classes.) - Each "message" (implemented as a dispatching function call) goes to exactly one object (or class). Any other objects mentioned are passive arguments. - When an object sends a message, it waits for the called object to complete its processing of the message (that is, for the return of the function call) before continuing. - One thread of control calls all objects; they are not independent active entities. Now, all reasonable languages are Turing-equivalent. I'm sure one could create, in C++, a system where all the objects are active and objects send each other messages without waiting for a response; or, one where several objects can work together co-equally to handle some messages; or one where object-level messages go to a queue in the object's class, and whatever object becomes free handles the next message from the queue. But each of these would be working against the object-oriented model built into the language. With Ada, one can do these things without working against the OO model of the language, because the OO model is more general. On the other hand, for work within the OO model of C++, you don't have as much method-specific support built into the language. On the other other hand, it's fairly easy to define a method in Ada where one gets a very C++ "feel." Mandate that every tagged type will be defined in its own library-level package, with nothing in that package except for the tagged type and its supporting class-level elements; every potentially dispatching subprogram must have a controlling first parameter. Voila, C++ style! The package is the equivalent of the "class" in C++. I'm not saying that C++ is "lesser," "worse" or "wrong," I'm just saying that it takes a different, but equally valid, design approach. The same is true for Ada. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Samuel Mize @ 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` David Starner ` (2 more replies) 0 siblings, 3 replies; 116+ messages in thread From: Hyman Rosen @ 1999-05-25 0:00 UTC (permalink / raw) Samuel Mize <smize@imagin.net> writes: > THE QUESTION: how does one do "mix-in" classes in C++? I'd bet a > nickel that you can, but I don't know the specific mechanism. The > "mix-in" metaphor is described in the Ada 95 Rationale, 4.6.2. I believe this Ada -- generic type S is abstract tagged private; package P is type T is abstract new S with private; -- operations on T private type T is abstract new S with record -- additional components end record; end P; corrsponds to this C++ -- template <typename S> class P { public: class T : public S { private: // additional components } }; and given some type A, one could declare objects of type P<A>::T. These objects are derived from A and also implement the extra operations of T. I haven't bothered to duplicate the 'abstract', but that's easily done by giving T an abstract destructor, ~T() = 0. > - The class is the primary form of data encapsulation. Classes support static data and function members, and nested classes. I believe that this gives C++ the equivalent of Ada's packages. > - Each "message" (implemented as a dispatching function call) goes > to exactly one object (or class). Any other objects mentioned are > passive arguments. How is this different from Ada? Does Ada allow dispatching on more than one argument? > - When an object sends a message, it waits for the called object > to complete its processing of the message (that is, for the return > of the function call) before continuing. > - One thread of control calls all objects; they are not independent > active entities. Well, no argument there. C++ does not have a language-defined parallel processing capability, and Ada is absolutely superior in that regard. However, I would say that this is generally considered orthogonal to object-oriented programming, since your statement above is equally true if you replace objects and messages with plain function calls. > I'm sure one could create, in C++ ... > But each of these would be working against the object-oriented model > built into the language. Instead, C++ programmers generally use third-party or system packages which allow parallel processing. These have no impact upon the OO model at all, and certainly don't forbid anything you might normally do. You do have to be careful about protecting shared resources, but that's true in Ada as well. I think including parallel behavior in your definition of OO is stretching that definition beyond any accepted usage. > I'm not saying that C++ is "lesser," "worse" or "wrong," I'm just saying > that it takes a different, but equally valid, design approach. The > same is true for Ada. To quote you, > There are other OO design approaches that are harder to implement in > C++ than in Ada, because C++ strongly supports one specific view of > object-oriented technology. See? You said there are OO approaches that are harder to implement in C++ than in Ada. If you're talking about implementing parallel processing, fine, I agree. Otherwise, I would like to see an example, so that I can determine whether that's really true, or whether it comes from an incomplete understanding of C++. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen @ 1999-05-25 0:00 ` David Starner 1999-05-26 0:00 ` Laurent Guerby 1999-05-26 0:00 ` Ole-Hjalmar Kristensen 2 siblings, 0 replies; 116+ messages in thread From: David Starner @ 1999-05-25 0:00 UTC (permalink / raw) Hyman Rosen wrote: > > - The class is the primary form of data encapsulation. > > Classes support static data and function members, and nested classes. > I believe that this gives C++ the equivalent of Ada's packages. Yes, but that approach is alien to C++, where as it's a natural approach in Ada. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` David Starner @ 1999-05-26 0:00 ` Laurent Guerby 1999-05-26 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Ole-Hjalmar Kristensen 2 siblings, 1 reply; 116+ messages in thread From: Laurent Guerby @ 1999-05-26 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> as > I believe this Ada -- > > generic > type S is abstract tagged private; > package P is > type T is abstract new S with private; > -- operations on T > private > type T is abstract new S with > record > -- additional components > end record; > end P; > > corrsponds to this C++ -- > [...] As for your quest of finding an example of an OO construct significantly easier in Ada than in C++, I don't think you'll find something were the difference in implementation is that great, the OO models are basically the same (but for multiple inheritance of course). I don't know if in C++ you can constrain a template type argument to be of a specific class (type and class in the Ada sense). Here is a slight variation of the Ada code you posted that uses this feature: package P is type T is tagged null record; -- T ops end P; with P; generic type GT is new P.T with private; -- This generic can be instanciated with any type in T'Class package G is -- I can call T ops on GT objects. type GGT is new GT with null record; -- GGT has T ops too. end G; The Ada OO model guarantees that no dispatch operation will run non-existing code (even in case of wild generics), I don't know if it's true of the C++ one. Okay, it doesn't make any OO construct easier, but you feel safer when this property is true ;-). Not directly linked to OO constructs (I agree in advance ;-): * In Ada, with discriminants you can easily have objects of varying size being stack allocated instead of heap allocated. On the notation size, I believe the Ada and C++ (vector<>) ways are equivalent but when you put parallelism in the loop it doesn't look quite the same, heap is global data so you have to lock when you use it, which can be troublesome in some cases performance-wise. * I don't know if self referencial types have a C++ equivalent (see the Ada rationale for an example of such beast). * You can "statically" create complex objects and elaboration issues are correctly handled by the Ada definition, I don't think it's the case in C++ (I think you don't know in what order the constructors will be called for "static" data in C++, I might be wrong). * What happens if a constructor or a destructor (C++ terminology) raises an exception is fully specified in Ada, in particular in case of a destructor exception, for each object in the scope its destructor is given a chance to run, when this is done a big general ooops exception is raised. I don't know if it is the case in C++. This applies too to function returning objects called as argument of another subprogam. --LG ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Laurent Guerby @ 1999-05-26 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby 0 siblings, 1 reply; 116+ messages in thread From: Hyman Rosen @ 1999-05-26 0:00 UTC (permalink / raw) Laurent Guerby <guerby@acm.org> writes: > I don't know if in C++ you can constrain a template type argument to > be of a specific class (type and class in the Ada sense). No, you can not. There are tricks that can accomplish the test, but they are tricks, not basic language features. The C++ approach to generics is "if it compiles, it works". Instead of restricting a parameter to be of a certain type, you just write the template as if the parameter has that type. It may be that a different type will support the operations equally well, in which case there is no reason to prevent the template from working. I understand that this is unpleasant for many people who want to be able to say and see exactly what's going on with the code. > The Ada OO model guarantees that no dispatch operation will run > non-existing code (even in case of wild generics), I don't know if > it's true of the C++ one. Yes, it's true. There will be either a compile-time or link-time error if non-exisiting code is referenced. In no case will the error be delayed to run-time. > * In Ada, with discriminants you can easily have objects of varying > size being stack allocated instead of heap allocated. In C++ as well. In C++, you use a template parameter - template <typename T, int N> struct Array { T a[N]; } Array<int,5> ai; Array<double,10> ad; Ada is somewhat ahead here, though, because (if I'm not mistaken) in Ada all the discrminated forms are the same type while in C++ they're not (i.e., in C++, Array<int,5> and Array<int,6> are completely unrelated). > * I don't know if self referencial types have a C++ equivalent (see > the Ada rationale for an example of such beast). struct SelfRef { SelfRef &Me; SelfRef() : Me(*this) { } }; > * You can "statically" create complex objects and elaboration issues > are correctly handled by the Ada definition, I don't think it's the > case in C++ (I think you don't know in what order the constructors > will be called for "static" data in C++, I might be wrong). For objects at file scope in a single compilation unit (a file), constructors are called in top-to-bottom order. For static objects within a function, constructors are called the first time the flow of control passes through the definition. Order of initialization across compilation units is unspecified. > * What happens if a constructor or a destructor (C++ terminology) > raises an exception is fully specified in Ada, in particular in case > of a destructor exception, for each object in the scope its destructor > is given a chance to run, when this is done a big general ooops > exception is raised. I don't know if it is the case in C++. This > applies too to function returning objects called as argument of > another subprogam. It's fully specified in C++ as well. When a constructor throws, any already constructed sub-components are destructed. As scopes are left in search of an exception handler, all constructed objects in those scopes are properly destructed. If during this process a destructor throws an exception unhandled within itself, a special termination handler is called. C++ cognoscenti have concluded that you should not throw exceptions from destructors because of this. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-26 0:00 ` Hyman Rosen @ 1999-05-28 0:00 ` Laurent Guerby 1999-06-01 0:00 ` Hyman Rosen 0 siblings, 1 reply; 116+ messages in thread From: Laurent Guerby @ 1999-05-28 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > No, you can not. There are tricks that can accomplish the test, but > they are tricks, not basic language features. The C++ approach to > generics is "if it compiles, it works". If I understand the rest of your posting, the C++ approach is "if it links, it works". You have to wait the linker to complain about mangled symbols not to be there to have the pleasure of trying to find out where you messed up your template ;-). > Instead of restricting a parameter to be of a certain type, you just > write the template as if the parameter has that type. It may be that > a different type will support the operations equally well, in which > case there is no reason to prevent the template from working. I > understand that this is unpleasant for many people who want to be > able to say and see exactly what's going on with the code. Strange, I would say that in Ada you doesn't have to know "exactly what's going on with the code" inside your generic to use and compile things, whereas in C++ you have to see the template code to see if your parameters will work. That's breaking some abstraction. In Ada: "if it compiles against the spec it works, regardless of the implementation". This favour distributed team work, properly abstracted generic specs and so ease build large reliable stuff. > In C++ as well. In C++, you use a template parameter - > > template <typename T, int N> struct Array { T a[N]; } > Array<int,5> ai; > Array<double,10> ad; > > Ada is somewhat ahead here, though, because (if I'm not mistaken) > in Ada all the discrminated forms are the same type while in C++ > they're not (i.e., in C++, Array<int,5> and Array<int,6> are > completely unrelated). Interesting ;-). Also Ada programmers tend to have big generic contracts (read lots of template arguments), I think the C++ notation will tend to be cumbersome if one complex template instanciation type is used a lot (well, you can #define then ;-). > For objects at file scope in a single compilation unit (a file), > constructors are called in top-to-bottom order. For static objects > within a function, constructors are called the first time the flow > of control passes through the definition. Order of initialization > across compilation units is unspecified. That was my point, unless you put everyting in a big C++ source file you cannot build statically (at elaboration time in the Ada world) complex objects implying multiple classes. BTW, thanks for bringing your C++ expertise on us poor Ada guyes, I really find your posts insightful on a lot of issues ;-). --LG ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-28 0:00 ` Laurent Guerby @ 1999-06-01 0:00 ` Hyman Rosen 1999-06-03 0:00 ` Fraser Wilson 0 siblings, 1 reply; 116+ messages in thread From: Hyman Rosen @ 1999-06-01 0:00 UTC (permalink / raw) Laurent Guerby <guerby@acm.org> writes: > If I understand the rest of your posting, the C++ approach is "if it > links, it works". You have to wait the linker to complain about > mangled symbols not to be there to have the pleasure of trying to find > out where you messed up your template ;-). You give source code to the compiler, and it gives you either a working executable, or a set of error messages explaining why it was unable to do so. Internal phases of the compiler's operation are not of interest to its user. If the error messages are unintelligible, then that is the fault of the compiler author. > Strange, I would say that in Ada you doesn't have to know > "exactly what's going on with the code" inside your generic > to use and compile things, whereas in C++ you have to > see the template code to see if your parameters will > work. That's breaking some abstraction. In C++ you generally rely upon documentation of the template parameters instead of actual restrictions, although it's possible to code those if you want to. The C++ Standard has a vocabulary of some typical examples (copy constructable, forward iterator, etc.). > In Ada: "if it compiles against the spec it works, regardless of the > implementation". This favour distributed team work, properly > abstracted generic specs and so ease build large reliable stuff. Probably so. > Interesting ;-). Also Ada programmers tend to have big generic > contracts (read lots of template arguments), I think the C++ notation > will tend to be cumbersome if one complex template instanciation type > is used a lot (well, you can #define then ;-). You would use a typedef, not a #define. And most templates I've seen have few parameters. Those with somewhat more tend to default the later ones so that they may be elided. > That was my point, unless you put everyting in a big C++ source file > you cannot build statically (at elaboration time in the Ada world) > complex objects implying multiple classes. I'm not sure what you mean here - an example would be useful. > BTW, thanks for bringing your C++ expertise on us poor Ada guyes, I > really find your posts insightful on a lot of issues ;-). I have never called anyone a "poor Ada guy", nor have I stated that C++ is a better language than Ada. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-01 0:00 ` Hyman Rosen @ 1999-06-03 0:00 ` Fraser Wilson 0 siblings, 0 replies; 116+ messages in thread From: Fraser Wilson @ 1999-06-03 0:00 UTC (permalink / raw) paene lacrimavi postquam Hyman Rosen <hymie@prolifics.com> scripsit: >You give source code to the compiler, and it gives you either a working >executable, or a set of error messages explaining why it was unable to >do so. Internal phases of the compiler's operation are not of interest >to its user. I disagree with this. One of the things I like about Ada is not having to wait until link time to find out that I forgot to implement a subprogram. It's not just a time factor; the Ada compiler will tell me exactly which package(s) failed to contain the required implementation; all the C or C++ compiler can say is that it didn't find something. It's even worse if, for example, a C or C++ library was written by somebody else, and that person neglected to implement something, but testing never picked it up because it was never called. >You would use a typedef, not a #define. And most templates I've seen >have few parameters. Those with somewhat more tend to default the >later ones so that they may be elided. Really? I can imagine that a large template would be tricky in C++, but it's straightforward in Ada (especially with named argument notation), and surprisingly useful. One particularly handy generic I wrote has 28 parameters ... I'd hate to see that attempted in a less wordy language. Sure, I make new instantiations of it with a bit of cut and paste, but it's really really easy to read, maintain and update. cheers, Fraser. (change i's to y's for my real email address) ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` David Starner 1999-05-26 0:00 ` Laurent Guerby @ 1999-05-26 0:00 ` Ole-Hjalmar Kristensen 2 siblings, 0 replies; 116+ messages in thread From: Ole-Hjalmar Kristensen @ 1999-05-26 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > Samuel Mize <smize@imagin.net> writes: > > THE QUESTION: how does one do "mix-in" classes in C++? I'd bet a > > nickel that you can, but I don't know the specific mechanism. The > > "mix-in" metaphor is described in the Ada 95 Rationale, 4.6.2. > > I believe this Ada -- > > generic > type S is abstract tagged private; > package P is > type T is abstract new S with private; > -- operations on T > private > type T is abstract new S with > record > -- additional components > end record; > end P; > > corrsponds to this C++ -- > > template <typename S> > class P > { > public: > class T : public S > { > private: > // additional components > } > }; > > and given some type A, one could declare objects of type P<A>::T. > These objects are derived from A and also implement the extra > operations of T. I haven't bothered to duplicate the 'abstract', > but that's easily done by giving T an abstract destructor, ~T() = 0. > In C++, you don't even need templates to do mix-in's. The following method will work: class a { public: virtual void f() = 0; }; class b: virtual public a { public: void g(){ .... f(); .... } }; class a_impl_1: virtual public a { public: void f(){ do_something(); } }; class a_impl_2: virtual public a { public: void f(){ do_something_else(); } }; class mixed1: public b, public a_impl_1{ }; class mixed2: public b, public a_impl_2{ }; Now, in mixed1, g will call a_impl_1::g(), and in mixed2, g will call a_impl_2::g(). Any function which is virtual in class a is accessible to any derived class, but the actual function which is called is determined at run time. The classes which are derived from a has to declare a as a virtual base class, or we would get multiple a's in mixed1 and mixed2, and the mechanism would not work. <stuff deleted> -- E pluribus Unix ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Robert Dewar 1999-05-25 0:00 ` Samuel Mize @ 1999-06-03 0:00 ` Matthew Heaney 1999-06-03 0:00 ` Hyman Rosen 2 siblings, 1 reply; 116+ messages in thread From: Matthew Heaney @ 1999-06-03 0:00 UTC (permalink / raw) Hyman Rosen <hymie@prolifics.com> writes: > Samuel Mize <smize@imagin.net> writes: > > There are other OO design approaches that are harder to implement in > > C++ than in Ada, because C++ strongly supports one specific view of > > object-oriented technology. > > Could you give an example of this? type Human_Type (<>) is tagged limited private; ... procedure Marry (Bride, Groom : in out Human_Type); This is a binary operation: Marry (Linda, Paul); The operation applies equally to both parties, so designating one object as the distinguished receiver would not capture the abstraction as well. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-06-03 0:00 ` Matthew Heaney @ 1999-06-03 0:00 ` Hyman Rosen 0 siblings, 0 replies; 116+ messages in thread From: Hyman Rosen @ 1999-06-03 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > type Human_Type (<>) is tagged limited private; > procedure Marry (Bride, Groom : in out Human_Type); > This is a binary operation: > Marry (Linda, Paul); > The operation applies equally to both parties, so designating one object > as the distinguished receiver would not capture the abstraction as well. I see. I think at this point, C++ programmers would have to code the tag test themselves, but then the usage would look very similar. struct Human_Type { friend Marry(Human_Type &a, Human_Type &b) { if (typeid(a) != typeid(b)) throw "Marriage of unequals!"; a.Marry(b); } private: virtual void Marry(Human_Type &other) = 0; }; struct Lord : Human_Type { private: virtual void Marry(Human_Type &other) { Lord &other_lord = static_cast<Lord &>(other); //... } }; ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 Ada OO Mechanism Shawn M. Root 1999-05-20 0:00 ` Samuel Mize @ 1999-05-21 0:00 ` Dale Stanbrough 1999-05-20 0:00 ` bob ` (2 more replies) 1 sibling, 3 replies; 116+ messages in thread From: Dale Stanbrough @ 1999-05-21 0:00 UTC (permalink / raw) " I would like to ask a question, however. In a recent thread entitled "A question for my personal knowledge" some people were saying that the Ada OO mechanism was counterintuitive. I tend to agree. This concern was dismissed by others as being merely "syntactic sugar", and claims were made that the Ada mechanism is actually easier to use than the C++ style." I actually like the method.operation notation, but I don't find the lack of it in Ada a really big problem. It _is_ syntactic sugar, in as much as there are no semantic differences that can be attributed to it. I think you get used to using whatever you use. Perhaps I would find method.operation marginally better (you can easily find the dispatching operand!), and it seems a bit more contextual (which i think is how people work). Dale ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Dale Stanbrough @ 1999-05-20 0:00 ` bob 1999-05-21 0:00 ` Dale Stanbrough 1999-05-21 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Don Overheu 2 siblings, 1 reply; 116+ messages in thread From: bob @ 1999-05-20 0:00 UTC (permalink / raw) In article <dale-2105990836310001@r1021c-18.ppp.cs.rmit.edu.au>, dale@cs.rmit.edu.au says... > >I actually like the method.operation notation, but I don't find the lack >of it in Ada a really big problem. It _is_ syntactic sugar, in as much as >there are no semantic differences that can be attributed to it. > Then why do most women say that they prefer it when a man talk love things to them in French than in any other language? It is true. Ask any woman. Why do "I love you" in French is more appealing to a woman ears than "I love you" in English or German or Russian etc? and they respond better to it that way? Same semantics, (expressing love), but different synatx (sound wise). So, what you think is only syntactic sugar, for others might be more. It might have some deeper feelings associated with it, that brings up some images associated with personal emotions. Bob who_needs_to_learn_french_to_improve_his_social_life ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-20 0:00 ` bob @ 1999-05-21 0:00 ` Dale Stanbrough 0 siblings, 0 replies; 116+ messages in thread From: Dale Stanbrough @ 1999-05-21 0:00 UTC (permalink / raw) bob wrote: " Same semantics, (expressing love), but different synatx (sound wise). So, what you think is only syntactic sugar, for others might be more. It might have some deeper feelings associated with it, that brings up some images associated with personal emotions." I'll keep that in mind next time I compile an Ada program with a woman as the target. Dale ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Dale Stanbrough 1999-05-20 0:00 ` bob @ 1999-05-21 0:00 ` Richard D Riehle 1999-05-21 0:00 ` Shawn M. Root 1999-05-21 0:00 ` Marin David Condic 1999-05-25 0:00 ` Don Overheu 2 siblings, 2 replies; 116+ messages in thread From: Richard D Riehle @ 1999-05-21 0:00 UTC (permalink / raw) In article <dale-2105990836310001@r1021c-18.ppp.cs.rmit.edu.au>, dale@cs.rmit.edu.au (Dale Stanbrough) wrote: >" I would like to ask a question, however. In a recent thread > entitled "A question for my personal knowledge" some people were saying > that the Ada OO mechanism was counterintuitive. I tend to agree. This > concern was dismissed by others as being merely "syntactic sugar", and > claims were made that the Ada mechanism is actually easier to use than > the C++ style." > >I actually like the method.operation notation, but I don't find the lack >of it in Ada a really big problem. It _is_ syntactic sugar, in as much as >there are no semantic differences that can be attributed to it. I know some languages in which the verb is the last word of a sentence. Some other languages are subject-verb-object, others have entirely different syntax. So when I hear someone say that Ada is counterintuitive or C++ is counterintuitive or Object COBOL is counterintuitive, I understand that they mean, "This is not the way I am used to thinking about things." That does not mean it is counterintuitive. It simply means they have had difficulty learning a new programming language just as they might have trouble learning a new spoken language. When I hear someone speak of "natural" language, I have to wonder what they are talking about. There is absolutely nothing wrong with the syntax of C++. Nothing wrong or counterintuitive about the syntax of Ada or Eiffel. And there is nothing counterintuitive about the object model of the emerging COBOL standard. If you want to say, "I am having trouble learning this language because it is not what I am used to," fine. That is accepting responsibility for your own difficulty. Lots of great ideas throughout history have been counterintuitive. The Greeks could not conceive of a symbol for zero. Aristotle thought it was intutitive to begin counting from two because there was no point in counting if there only a single instance. Before the invention of calculus, the notion of a limit was counterintuitive. The statement, "I find such and such to be counterintuitive," is a tired old excuse for failing to work hard enough to understand some idea. It does not apply to languages; especially not to programming languages. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Richard D Riehle @ 1999-05-21 0:00 ` Shawn M. Root 1999-05-21 0:00 ` Richard D Riehle 1999-05-21 0:00 ` Marin David Condic 1 sibling, 1 reply; 116+ messages in thread From: Shawn M. Root @ 1999-05-21 0:00 UTC (permalink / raw) Richard D Riehle wrote in message <7i28qu$1bc@dfw-ixnews11.ix.netcom.com>... :In article <dale-2105990836310001@r1021c-18.ppp.cs.rmit.edu.au>, : dale@cs.rmit.edu.au (Dale Stanbrough) wrote: : :>" I would like to ask a question, however. In a recent thread :> entitled "A question for my personal knowledge" some people were saying :> that the Ada OO mechanism was counterintuitive. I tend to agree. This :> concern was dismissed by others as being merely "syntactic sugar", and :> claims were made that the Ada mechanism is actually easier to use than :> the C++ style." :> :>I actually like the method.operation notation, but I don't find the lack :>of it in Ada a really big problem. It _is_ syntactic sugar, in as much as :>there are no semantic differences that can be attributed to it. : :I know some languages in which the verb is the last word of a sentence. :Some other languages are subject-verb-object, others have entirely :different syntax. So when I hear someone say that Ada is :counterintuitive or C++ is counterintuitive or Object COBOL is :counterintuitive, I understand that they mean, "This is not the way :I am used to thinking about things." That does not mean it is :counterintuitive. It simply means they have had difficulty learning :a new programming language just as they might have trouble learning a :new spoken language. When I hear someone speak of "natural" language, :I have to wonder what they are talking about. : Actually it does mean that it is counterintuitive. Counterintuitive means that what you found is not what you expected to find. This is a relative term, not an absolute. What is counterintuitive for me, may be readily obvious to you. Intuition has nothing to do with "thinking about things". It has to do with the understanding or knowing of something _without_ overt reasoning. Furthermore, it does not mean that someone had difficulty learning a new programming language. It simply means that, in my particular case, the Ada OO mechanisms seem less obvious than the C++ mechanisms. :There is absolutely nothing wrong with the syntax of C++. Nothing :wrong or counterintuitive about the syntax of Ada or Eiffel. And :there is nothing counterintuitive about the object model of the :emerging COBOL standard. If you want to say, "I am having trouble :learning this language because it is not what I am used to," fine. :That is accepting responsibility for your own difficulty. Lots of :great ideas throughout history have been counterintuitive. The :Greeks could not conceive of a symbol for zero. Aristotle thought :it was intutitive to begin counting from two because there was no :point in counting if there only a single instance. Before the :invention of calculus, the notion of a limit was counterintuitive. : Yes, but after calculus was invented, and the concept of the limit was understood, would you invent a new way to do limits if the new way offered no significant advantages over the old way? :The statement, "I find such and such to be counterintuitive," is a :tired old excuse for failing to work hard enough to understand some :idea. It does not apply to languages; especially not to programming :languages. : Again, I don't know where you got this impression. Perhaps others you've spoken to have used the "counterintuitive excuse" to cover difficulties in learning. However, that is not the case here. I was introduced to Ada before C++ so, if anything, I had more trouble learning the C++ way of doing things. My comments have nothing to do with not working hard enough to understand certain ideas. I understand the ideas and concepts involved. I understand the other side's arguments. So far, however, I don't agree with them. -- Shawn M. Root ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Shawn M. Root @ 1999-05-21 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Shawn M. Root 0 siblings, 1 reply; 116+ messages in thread From: Richard D Riehle @ 1999-05-21 0:00 UTC (permalink / raw) In article <7i2pqn$qak$1@news.orbitworld.net>, "Shawn M. Root" <smroot@orbitworld.net> wrote: >:So when I hear someone say that Ada is >:counterintuitive or C++ is counterintuitive or Object COBOL is >:counterintuitive, I understand that they mean, "This is not the way >:I am used to thinking about things." That does not mean it is >:counterintuitive. It simply means they have had difficulty learning >:a new programming language just as they might have trouble learning a >:new spoken language. When I hear someone speak of "natural" language, >:I have to wonder what they are talking about. >: >Actually it does mean that it is counterintuitive. Counterintuitive >means that what you found is not what you expected to find. This is a >relative term, not an absolute. What is counterintuitive for me, may >be readily obvious to you. Intuition has nothing to do with "thinking >about things". I wonder if I want someone writing software for a pacemaker who is not "thinking about things." Intuition strikes me as a psychological concept that implies that one is "thinking about things" differently than through the use of more ordinary reasoning. I am willing to accept the notion of intuition as an important element of problem solving. However, the more I consider the term "counterintuitive" the more counterintuitive it seems the word might be. Perhaps it is a self-cancelling concept, sort of like (A or not A). >It has to do with the understanding or knowing of >something _without_ overt reasoning. Furthermore, it does not mean >that someone had difficulty learning a new programming language. It >simply means that, in my particular case, the Ada OO mechanisms seem >less obvious than the C++ mechanisms. The fact that some idea is not obvious makes it counterintuitive? That notion, in itself, should make one suspicious of any effort to reach a conclusion by declaring that this or that is counterintuitive. Once again reaching far back in the history of mathematics, when algorismics was introduced to Europe, there was a great uproar. People found their abacus-based counting much more comfortable, much more intutitive. The fact that it originated in a non-Christian community made it even more unacceptable to many. Today, the principles of accounting are a vestige of the early abacus-based model, and accounting is regarded by many algebraicists as being counterintuitive. I do not believe one should become too comfortable with the notion of counterintuitive as an excuse for failure to learn some new idea. In such cases, the failure may be that of the learner, not of the idea. > >Yes, but after calculus was invented, and the concept of the limit was >understood, would you invent a new way to do limits if the new way >offered no significant advantages over the old way? The notion of limit did occur to earlier mathematics. It was simply not adopted, perhaps because it was counterintuitive. If you have watched young freshman struggle with calculus, even today, the idea of limit still remains counterintuitive for many of them. > >Again, I don't know where you got this impression. Perhaps others >you've spoken to have used the "counterintuitive excuse" to cover >difficulties in learning. However, that is not the case here. I was >introduced to Ada before C++ so, if anything, I had more trouble >learning the C++ way of doing things. My comments have nothing to do >with not working hard enough to understand certain ideas. I understand >the ideas and concepts involved. I understand the other side's >arguments. So far, however, I don't agree with them. Perhaps it depends on where one stands to examine the issues. Certainly, it is depends on what _arbitrary_ foundations one selects to support the argument. When I look at a pencil immersed in water, it is clear to me that the pencil becomes bent. Unless I understand some additional physics, I will not realize that the pencil is not actually bent, even though it seems so obvious from my simple viewpoint that it is. It seems to me that, when evaluating software tools and languages, we need a more comprehensive view of the problem, one that does not reject some perfectly good approach by suggesting that some starting point for a solution seems counterintuitive. It is often the intuition on which the counterintuitive conclusion is based that makes the counterintuitive viewpoint the best place to begin looking for a solution. If Ada is counterintuitive, perhaps that is a good thing, especially when seeking solutions to problems of designing large-scale, safety-critical software. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Richard D Riehle @ 1999-05-25 0:00 ` Shawn M. Root 0 siblings, 0 replies; 116+ messages in thread From: Shawn M. Root @ 1999-05-25 0:00 UTC (permalink / raw) Richard D Riehle wrote in message <7i4brh$hi2@dfw-ixnews8.ix.netcom.com>... :In article <7i2pqn$qak$1@news.orbitworld.net>, : "Shawn M. Root" <smroot@orbitworld.net> wrote: : :>:So when I hear someone say that Ada is :>:counterintuitive or C++ is counterintuitive or Object COBOL is :>:counterintuitive, I understand that they mean, "This is not the way :>:I am used to thinking about things." That does not mean it is :>:counterintuitive. It simply means they have had difficulty learning :>:a new programming language just as they might have trouble learning a :>:new spoken language. When I hear someone speak of "natural" language, :>:I have to wonder what they are talking about. :>: :>Actually it does mean that it is counterintuitive. Counterintuitive :>means that what you found is not what you expected to find. This is a :>relative term, not an absolute. What is counterintuitive for me, may :>be readily obvious to you. Intuition has nothing to do with "thinking :>about things". : : I wonder if I want someone writing software for a pacemaker who is : not "thinking about things." Of course you don't. Neither do I. : Intuition strikes me as a psychological : concept that implies that one is "thinking about things" differently : than through the use of more ordinary reasoning. Perhaps this will help. http://www.m-w.com/dictionary.htm : I am willing to : accept the notion of intuition as an important element of problem : solving. Exactly right. It is _only_ an element in problem solving; not the means to a complete solution. <snip> : :>It has to do with the understanding or knowing of :>something _without_ overt reasoning. Furthermore, it does not mean :>that someone had difficulty learning a new programming language. It :>simply means that, in my particular case, the Ada OO mechanisms seem :>less obvious than the C++ mechanisms. : : The fact that some idea is not obvious makes it counterintuitive? That : notion, in itself, should make one suspicious of any effort to reach : a conclusion by declaring that this or that is counterintuitive. Again, I have to agree with you. Noting that something is counterintuitive may raise a question, but should not provide a conclusion. <snip> : : I do not believe one should become too comfortable with the notion of : counterintuitive as an excuse for failure to learn some new idea. In : such cases, the failure may be that of the learner, not of the idea. True. In fact, questioning _why_ the idea is counterintuitive may bring about a deeper understanding of both the new and older, related ideas. This was the intent of my original post. I just want to understand why tagged types were used instead of the seemingly more popular class structure. :> :>Yes, but after calculus was invented, and the concept of the limit was :>understood, would you invent a new way to do limits if the new way :>offered no significant advantages over the old way? : : The notion of limit did occur to earlier mathematics. It was simply : not adopted, perhaps because it was counterintuitive. If you have : watched young freshman struggle with calculus, even today, the idea : of limit still remains counterintuitive for many of them. : Perhaps I should have said "adopted" then, instead of "understood." The question remains. :> :>Again, I don't know where you got this impression. Perhaps others :>you've spoken to have used the "counterintuitive excuse" to cover :>difficulties in learning. However, that is not the case here. I was :>introduced to Ada before C++ so, if anything, I had more trouble :>learning the C++ way of doing things. My comments have nothing to do :>with not working hard enough to understand certain ideas. I understand :>the ideas and concepts involved. I understand the other side's :>arguments. So far, however, I don't agree with them. : : Perhaps it depends on where one stands to examine the issues. Certainly, : it is depends on what _arbitrary_ foundations one selects to support : the argument. When I look at a pencil immersed in water, it is clear : to me that the pencil becomes bent. Unless I understand some additional : physics, I will not realize that the pencil is not actually bent, : even though it seems so obvious from my simple viewpoint that it is. : True, but how often do you need to know the physics? If I'm building a house, I don't need to know that a boards solidity is a result of an interplay of forces between widely spaced atoms. I just need to know that if I nail it to this other board, it will stay there. : It seems to me that, when evaluating software tools and languages, we : need a more comprehensive view of the problem, one that does not reject : some perfectly good approach by suggesting that some starting point for : a solution seems counterintuitive. Fine. Then the comprehensive solution should not dismiss out of hand the fact that an approach seems counterintuitive. Most definitely not in a language which has as one of it's goals, readability. : It is often the intuition on which : the counterintuitive conclusion is based that makes the counterintuitive : viewpoint the best place to begin looking for a solution. : If Ada is : counterintuitive, perhaps that is a good thing, especially when seeking : solutions to problems of designing large-scale, safety-critical software. : I'm not sure how a counterintuitive language is supposed to promote better design. That said, I really don't think that Ada is counterintuitive. It is a very natural feeling language. I just have issues with why the tagged type was used instead of a class construct. Since my original post, I have had conversations (sometimes loud) with one of our local Ada experts. He has given me many reasons why tagged types were used instead of a class. Samuel Mize's post was also very illuminating. They have at least left me reassured that the choice wasn't entirely arbitrary. It is disheartening, however, since I believe that this could hurt Ada's chances for increased popularity. It would be nice to see more and varied use of Ada. The response I received to my question was also a bit disheartening. With the exception of Mr. Mize, whose response was very helpful, I received no other answers to my questions. Perhaps I would've gotten better results with a "How do I send text to the screen?" question. -- Shawn M. Root ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Richard D Riehle 1999-05-21 0:00 ` Shawn M. Root @ 1999-05-21 0:00 ` Marin David Condic 1999-05-21 0:00 ` Steve 1999-05-21 0:00 ` Dan Nagle 1 sibling, 2 replies; 116+ messages in thread From: Marin David Condic @ 1999-05-21 0:00 UTC (permalink / raw) Richard D Riehle wrote: > > The statement, "I find such and such to be counterintuitive," is a > tired old excuse for failing to work hard enough to understand some > idea. It does not apply to languages; especially not to programming > languages. > Dittos! I think this probably also applies to the "first language" theory of programming and explains why lots of programmers accustomed to Fortran had such hostility towards Ada. My first language was Pascal and I found Ada to be quite comfortable, albeit substantially larger. I did quite a bit of Fortran programming, but always keeping in mind Pascal's flow structures, etc., which resulted in much more reliable and easier to understand Fortran code. Yet people I knew who had dealt strictly with Fortran found it difficult to deal with things like defining variables before they used them, lack of common blocks, etc. Programming in a new language definitely requires that you give up your preconceived notions of how something "ought" to look. MDC -- Marin David Condic Real Time & Embedded Systems, Propulsion Systems Analysis United Technologies, Pratt & Whitney, Large Military Engines M/S 731-95, P.O.B. 109600, West Palm Beach, FL, 33410-9600 ***To reply, remove "bogon" from the domain name.*** Visit my web page at: http://www.flipag.net/mcondic ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Marin David Condic @ 1999-05-21 0:00 ` Steve 1999-05-21 0:00 ` Dan Nagle 1 sibling, 0 replies; 116+ messages in thread From: Steve @ 1999-05-21 0:00 UTC (permalink / raw) In article <37457752.7A73DF4D@pwfl.com>, Marin says... >I did quite a >bit of Fortran programming, but always keeping in mind Pascal's flow >structures, etc., which resulted in much more reliable and easier to >understand Fortran code. Yet people I knew who had dealt strictly with >Fortran found it difficult to deal with things like defining variables >before they used them, lack of common blocks, etc. The reason they had trouble with it, is simple. FORTRAN programmers, by definition, are mostly scientists and engineers from different disciplines other than computer science, i.e. their main profession is not software, but they use software as a tool to do help them with their main profession, which is engineering (such as Civil eng., electrical, etc..) So, as long as it what they wrote works, they do not understand why you need to spend more time to 'improve' it. I've had to maintain and fix code written by PhD's in other fields and engineers like the above, and they write the worst code any one can see. I think there should be a rule against those people writing code, at least code that need to be maintained by someone else. Imagine if you had hard time dealing with FORTRAN written by those people, I had to look at Pearl code written by them! I had nightmares for days after that experience. Steve ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Marin David Condic 1999-05-21 0:00 ` Steve @ 1999-05-21 0:00 ` Dan Nagle 1999-05-24 0:00 ` Marin David Condic 1 sibling, 1 reply; 116+ messages in thread From: Dan Nagle @ 1999-05-21 0:00 UTC (permalink / raw) Hello, Marin David Condic wrote: > <snip requoted > > I think this probably also applies to the "first language" theory of > programming and explains why lots of programmers accustomed to Fortran > had such hostility towards Ada. Well, my first language (after assembler) was Fortran, and I'm finding Ada to be one of the most attractive languages around. I think both Fortran and Ada are high level languages designed for a particular pupose(s) and which are both very pratical languages for programming. Both exhibit a high degree of awareness of and sympathy to optimization issues, and generally with issues of what's going on under-the-hood. > My first language was Pascal and I found > Ada to be quite comfortable, albeit substantially larger. I did quite a > bit of Fortran programming, but always keeping in mind Pascal's flow > structures, etc., which resulted in much more reliable and easier to > understand Fortran code. Yet people I knew who had dealt strictly with > Fortran found it difficult to deal with things like defining variables > before they used them, lack of common blocks, etc. Again, my experiences are different. I've always found Fortran programmers treated COMMONs as just another kind of data declared in the main program. I believe the Fortran standards committee is looking at Ada as they work out how OO will appear in Fortran. > Programming in a new > language definitely requires that you give up your preconceived notions > of how something "ought" to look. Agreed. What's interesting to me is how different folks can program in the same language and come away with such different viewpoints. To me, Pascal has always been baby-Fortran with a lot of restrictive rules (and the unspoken claim that following the rules meant you'd never make a logic error!). <snip sig> -- Cheers! Dan Nagle dnagle@erols.com Purple Sage Computing Solutions, Inc. ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Dan Nagle @ 1999-05-24 0:00 ` Marin David Condic 0 siblings, 0 replies; 116+ messages in thread From: Marin David Condic @ 1999-05-24 0:00 UTC (permalink / raw) Dan Nagle wrote: > > Well, my first language (after assembler) was Fortran, and I'm finding > Ada to be one of the most attractive languages around. > No argument here - I think lots of people are capable of switching from any one language to any other and knowledge of any one language does not "cripple" someone's ability to use the other. My point was that there were lots of Fortran programmers who I knew resisted Ada because it wasn't Fortran with a slightly different syntax. They were used to a certain style and didn't want to (or know how to) put it aside and look at Ada without the preconceived notions. > I think both Fortran and Ada are high level languages designed for > a particular pupose(s) and which are both very pratical languages > for programming. Both exhibit a high degree of awareness of and > sympathy to optimization issues, and generally with issues of > what's going on under-the-hood. > I'm glad you mention the "sympathy for optimization" aspects. Ada took a lot of dings in its early days for being slow. I think it was a case of compiler writers not yet understanding the language and building partial implementations which wound up hamstrung when the more complicated features were to be addressed. That always bothered me because I didn't see anything in the language rules which would make it inherently inefficient. Obviously, these days, good quality optimization is being done and Ada code tends to be on a par with Fortran for speed. (In most cases - YMMV - implementation dependent - other general disclaimers! :-) > > I believe the Fortran standards committee is looking at Ada as they > work out how OO will appear in Fortran. > It would be wise for any standards committee to look at how things are done in other languages. I think Ada has a lot to offer in the way of insights on how to go about implementing OO in a "general purpose" language. > Agreed. What's interesting to me is how different folks can program > in the same language and come away with such different viewpoints. > To me, Pascal has always been baby-Fortran with a lot of restrictive > rules (and the unspoken claim that following the rules meant you'd > never make a logic error!). > I had always considered the block-structured, declare-before-use, "restrictive rules" aspects of Pascal (along with its small size in the original incarnation) was dramatically different from Fortran. But I suppose it is closer to Fortran than, say, Lisp. So I guess there are perspective issues too. MDC -- Marin David Condic Real Time & Embedded Systems, Propulsion Systems Analysis United Technologies, Pratt & Whitney, Large Military Engines M/S 731-95, P.O.B. 109600, West Palm Beach, FL, 33410-9600 ***To reply, remove "bogon" from the domain name.*** Visit my web page at: http://www.flipag.net/mcondic ^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: Ada OO Mechanism 1999-05-21 0:00 ` Dale Stanbrough 1999-05-20 0:00 ` bob 1999-05-21 0:00 ` Richard D Riehle @ 1999-05-25 0:00 ` Don Overheu 2 siblings, 0 replies; 116+ messages in thread From: Don Overheu @ 1999-05-25 0:00 UTC (permalink / raw) I have just caught up with Tucker Taft's response to this thread querying the speed of Ada95. In his gentle way he suggests that the pixel display is to blame for any perceived slowness in running a Mandelbrot example. Perhaps what he was saying was that the problem may resides in the operating system or the underlying hardware not the Ada95 program or C. I happen to have Jerry Van Dijk's Mandelbrot example to run under DOS. It is almost identical to Tucker Taft's example. I have recompiled it for Jerry's Adagraph to run under Win95. Here are the results. DOS: Screen size 640 by 480, run time 5 secs Win95: Adagraph Screen size set to 640 by 480, run time 80 secs (that is not a misprint!). With pixel plotting removed as suggested by Tucker Taft, run time is 5 secs Equipment: 300Mh Pentium II Celeron, 65Mb RAM, 4Mb video card and 4Gb hard disc Don Overheu ^ permalink raw reply [flat|nested] 116+ messages in thread
end of thread, other threads:[~1999-06-14 0:00 UTC | newest] Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-05-20 0:00 Ada OO Mechanism Shawn M. Root 1999-05-20 0:00 ` Samuel Mize 1999-05-20 0:00 ` David Botton 1999-05-20 0:00 ` Samuel Mize 1999-05-20 0:00 ` David Botton 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Robert Dewar 1999-05-24 0:00 ` Hyman Rosen 1999-05-24 0:00 ` Mike 1999-05-25 0:00 ` Robert Dewar 1999-05-24 0:00 ` David Starner 1999-05-24 0:00 ` bob 1999-05-24 0:00 ` David Starner 1999-05-25 0:00 ` Ole-Hjalmar Kristensen 1999-05-25 0:00 ` Florian Weimer 1999-05-25 0:00 ` Mark A Biggar 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Ray Blaak 1999-05-26 0:00 ` Hyman Rosen 1999-05-26 0:00 ` Richard D Riehle 1999-05-26 0:00 ` Hyman Rosen 1999-05-27 0:00 ` Richard D Riehle 1999-06-05 0:00 ` Matthew Heaney 1999-06-07 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby 1999-06-05 0:00 ` Matthew Heaney 1999-06-07 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Matthew Heaney 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Samuel Mize 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Robert Dewar 1999-06-08 0:00 ` Markus Kuhn 1999-06-08 0:00 ` Stanley R. Allen 1999-06-08 0:00 ` Stanley R. Allen [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <t7emjmmx8w.fsf@calumny.jyacc.com> 1999-06-08 0:00 ` Larry Kilgallen 1999-06-08 0:00 ` Hyman Rosen 1999-06-08 0:00 ` Tucker Taft 1999-06-08 0:00 ` Brian Rogoff [not found] ` < <375E92CB.27850620@averstar.com> 1999-06-09 0:00 ` Brian Rogoff 1999-06-14 0:00 ` Robert A Duff 1999-06-09 0:00 ` Robert Dewar 1999-06-09 0:00 ` Tucker Taft 1999-06-09 0:00 ` Samuel Mize 1999-06-09 0:00 ` Matthew Heaney [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <t7r9nmz8ou.fsf@calumny.jyacc.com> 1999-06-08 0:00 ` Larry Kilgallen 1999-06-08 0:00 ` Hyman Rosen 1999-06-14 0:00 ` Robert A Duff [not found] ` <t7zp2sr6yf.fsf@calumny.jyacc.c <375d9a3d.e1cccc63@averstar.com> 1999-06-09 0:00 ` Larry Kilgallen 1999-06-09 0:00 ` Tucker Taft 1999-05-25 0:00 ` Brian Rogoff 1999-05-25 0:00 ` Jim 1999-05-26 0:00 ` Robert Dewar 1999-05-26 0:00 ` Brian Rogoff 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Chris 1999-05-25 0:00 ` David Botton 1999-05-27 0:00 ` Aidan Skinner 1999-05-27 0:00 ` Gautier 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby 1999-05-28 0:00 ` Richard D Riehle 1999-05-28 0:00 ` Tom Moran 1999-05-28 0:00 ` Samuel Mize 1999-05-27 0:00 ` Samuel Mize 1999-05-27 0:00 ` Jon S Anthony 1999-05-25 0:00 ` Richard D Riehle 1999-05-25 0:00 ` David Botton 1999-05-26 0:00 ` Tom Moran 1999-05-27 0:00 ` Aidan Skinner 1999-05-28 0:00 ` Robert I. Eachus 1999-05-28 0:00 ` Brian Rogoff 1999-05-29 0:00 ` Ehud Lamm 1999-05-30 0:00 ` chris 1999-05-30 0:00 ` Harry George 1999-05-30 0:00 ` Vladimir Olensky 1999-05-31 0:00 ` Robert Dewar 1999-05-30 0:00 ` Robert Dewar 1999-05-31 0:00 ` Vladimir Olensky 1999-06-03 0:00 ` Dale Stanbrough 1999-06-02 0:00 ` mike 1999-06-03 0:00 ` Robert Dewar 1999-06-06 0:00 ` David Botton 1999-06-07 0:00 ` Robert Dewar 1999-06-01 0:00 ` Richard D Riehle 1999-06-03 0:00 ` Matthew Heaney 1999-06-03 0:00 ` Matthew Heaney 1999-05-25 0:00 ` Samuel Mize 1999-05-25 0:00 ` Hyman Rosen 1999-05-25 0:00 ` David Starner 1999-05-26 0:00 ` Laurent Guerby 1999-05-26 0:00 ` Hyman Rosen 1999-05-28 0:00 ` Laurent Guerby 1999-06-01 0:00 ` Hyman Rosen 1999-06-03 0:00 ` Fraser Wilson 1999-05-26 0:00 ` Ole-Hjalmar Kristensen 1999-06-03 0:00 ` Matthew Heaney 1999-06-03 0:00 ` Hyman Rosen 1999-05-21 0:00 ` Dale Stanbrough 1999-05-20 0:00 ` bob 1999-05-21 0:00 ` Dale Stanbrough 1999-05-21 0:00 ` Richard D Riehle 1999-05-21 0:00 ` Shawn M. Root 1999-05-21 0:00 ` Richard D Riehle 1999-05-25 0:00 ` Shawn M. Root 1999-05-21 0:00 ` Marin David Condic 1999-05-21 0:00 ` Steve 1999-05-21 0:00 ` Dan Nagle 1999-05-24 0:00 ` Marin David Condic 1999-05-25 0:00 ` Don Overheu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox