* Not intended for use in medical, @ 1997-04-23 0:00 Robert C. Leif, Ph.D. 1997-04-24 0:00 ` J. Florio ` (3 more replies) 0 siblings, 4 replies; 120+ messages in thread From: Robert C. Leif, Ph.D. @ 1997-04-23 0:00 UTC (permalink / raw) To: Tim Behrendsen, Kaz Kylheku et al. From: Robert C. Leif, Ph.D. Vice President Ada_Med The quote," Intel products are not intended for use in medical, life saving, or life sustaining applications." as you stated is in Pentium Processor Specification Update_ from Intel, January 1997. I called Intel. The document can be ordered at 800.548.4725. Intel said that there was no charge. The National 32 bit processor had a similar disclaimer. Do you or any of the other readers of Comp.Lang.Ada know of other similar disclaimers? Many medical instruments use Intel 486 and Pentium devices. This quote may provide an excellent opportunity in the medical device business, which is NOT puny. My question is, Does validation of an Ada compiler on a platform provide significant evidence that the processor produces valid object code? Would any of the other Ada test suites help? I deliberately used the word significant rather than sufficient. If anyone knows how to prove sufficiency, I would also like a comment. Any other suggestions that would permit realistic development of medical devices would be appreciated. Microsoft would be well advised to include this type of disclaimer. Actually, Bill Gates would be best advised to suggest that medical device manufacturers purchase Ada compilers. Microsoft is a product liability lawyer's dream come true, real deep pockets. Many medical devices are hosted on Windows and Windows NT Intel computers. Macintoshes are also used. Although the lawyers are of interest, the response of the FDA will be more interesting. You wrote ---------------------------------------------------------------- Date: Fri, 18 Apr 1997 14:18:41 GMT From: Tim Behrendsen <tim@A-SIS.COM> Subject: Re: Any research putting c above ada? Kaz Kylheku <kaz@vision.crest.nt.com> wrote in article <5j5kqf$adm@bcrkh13.bnr.ca>... > Consider this: SNIP > Intel products are not intended for use in medical, life saving, or > life sustaining applications. > > This quote is taken from _Pentium Processor Specification Update_ from Intel, > January 1997. It is in the very first disclaimer paragraph on the inside > front cover. The reason is probably that the medical market is so puny that they figured it wasn't worth being dragged into a lawsuit if a medical manufacturer was sued. That sounds like lawyer-speak to me. ---------------------------------------------------------------------------- ----------- ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-23 0:00 Not intended for use in medical, Robert C. Leif, Ph.D. @ 1997-04-24 0:00 ` J. Florio 1997-04-25 0:00 ` Ken Garlington ` (2 subsequent siblings) 3 siblings, 0 replies; 120+ messages in thread From: J. Florio @ 1997-04-24 0:00 UTC (permalink / raw) Robert C. Leif, Ph.D. wrote: > To: Tim Behrendsen, Kaz Kylheku et al. > From: Robert C. Leif, Ph.D. > Vice President Ada_Med > > The quote," Intel products are not intended for use in medical, life > > saving, or life sustaining applications." as you stated is in > Pentium > Processor Specification Update_ from Intel, January 1997. I called > Intel. > The document can be ordered at 800.548.4725. Intel said that there > was no > charge. The National 32 bit processor had a similar disclaimer. Do > you or > any of the other readers of Comp.Lang.Ada know of other similar > disclaimers? Many medical instruments use Intel 486 and Pentium > devices. > > This quote may provide an excellent opportunity in the medical > device > business, which is NOT puny. My question is, Does validation of an > Ada > compiler on a platform provide significant evidence that the > processor > produces valid object code? Would any of the other Ada test suites > help? > I deliberately used the word significant rather than sufficient. If > anyone > knows how to prove sufficiency, I would also like a comment. Any > other > suggestions that would permit realistic development of medical > devices > would be appreciated. If one could provide such evidence (or prove it) it wouldn't solve the problem. What you really need to do is warrent that the program does what it's supposed to (all the compiler does is convert the instructions from one form to another -- granted that's an opportunity for additional errors to be injected). If you write an instruction to add 2 numbers and you were supposed to subtract them, the compiler won't save you. I would guess you see such disclaimers (opinion on) because the manufacturer doesn't want to warrent that the hardware itself doesn't have some insidious little problem (remember the big pentium flap when they first came out?). There's more than one or two gates on those little buggers these days! Life-critical systems need to worry about uninterruptable power as well as their "correctness". There are some problem domains that have made progress in proving the "correctness" of the application (e.g. communications), but to my knowledge, most complex systems that are life critical still focus on rigor in the development process and test, test , test, test (e.g. space shuttle) as well as approaches such as redundent systems, voting systems, separately developed systems, etc. Do a search for "high availability systems" and you'll probably come up with a few pointers.... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-23 0:00 Not intended for use in medical, Robert C. Leif, Ph.D. 1997-04-24 0:00 ` J. Florio @ 1997-04-25 0:00 ` Ken Garlington 1997-04-25 0:00 ` Kevin Cline 1997-04-28 0:00 ` John Apa 3 siblings, 0 replies; 120+ messages in thread From: Ken Garlington @ 1997-04-25 0:00 UTC (permalink / raw) Robert C. Leif, Ph.D. wrote: > > [SNIP] > My question is, Does validation of an Ada > compiler on a platform provide significant evidence that the processor > produces valid object code? It's subjective, of course, but I would say that it is not _significant_ evidence. Useful, perhaps, but not significant. > Would any of the other Ada test suites help? The NPL sells a test suite that is supposed to help, but I have no experience with it. > I deliberately used the word significant rather than sufficient. If anyone > knows how to prove sufficiency, I would also like a comment. Any other > suggestions that would permit realistic development of medical devices > would be appreciated. My experience is that the test suite needs to closely match the programming style, algorithm types, data structure types, compiler option usage, and other attributes of the application and its development approach. We have also had good success with the use of object-level structural coverage as a supplement to the "standard" testing approaches (see DO-178). -- LMTAS - The Fighter Enterprise - "Our Brand Means Quality" For job listings, other info: http://www.lmtas.com or http://www.lmco.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-23 0:00 Not intended for use in medical, Robert C. Leif, Ph.D. 1997-04-24 0:00 ` J. Florio 1997-04-25 0:00 ` Ken Garlington @ 1997-04-25 0:00 ` Kevin Cline 1997-04-25 0:00 ` Robert Dewar 1997-04-28 0:00 ` John Apa 3 siblings, 1 reply; 120+ messages in thread From: Kevin Cline @ 1997-04-25 0:00 UTC (permalink / raw) "Robert C. Leif, Ph.D." <rleif@RLEIF.COM> wrote: > >To: Tim Behrendsen, Kaz Kylheku et al. >From: Robert C. Leif, Ph.D. >Vice President Ada_Med > >The quote," Intel products are not intended for use in medical, life >saving, or life sustaining applications." as you stated is in Pentium >Processor Specification Update_ from Intel, January 1997. I called Intel. >The document can be ordered at 800.548.4725. Intel said that there was no >charge. The National 32 bit processor had a similar disclaimer. Do you or >any of the other readers of Comp.Lang.Ada know of other similar >disclaimers? Many medical instruments use Intel 486 and Pentium devices. > >This quote may provide an excellent opportunity in the medical device >business, which is NOT puny. However, it is a tiny fraction of the total chip market. > My question is, Does validation of an Ada >compiler on a platform provide significant evidence that the processor >produces valid object code? It didn't for Ada-83. In 1991 I found code generation bgs in both the validated Verdix compiler and the validated Telesoft compiler. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-25 0:00 ` Kevin Cline @ 1997-04-25 0:00 ` Robert Dewar 0 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-04-25 0:00 UTC (permalink / raw) Kevin Cline said <<> My question is, Does validation of an Ada >compiler on a platform provide significant evidence that the processor >produces valid object code? It didn't for Ada-83. In 1991 I found code generation bgs in both the validated Verdix compiler and the validated Telesoft compiler.>> You are answering the wrong question. YES, validatoin provides significant evidence that the processor produces valid object code, NO it dos not prove that the processor produces valid object code in all cases. This is a very important distinction. People tend to rattle bewtween these two positions: 1. Validation proves that a compiler is completely correct 2. Validation is useless, validated compilers still have bugs The truth is between, and nicely captured by the "significant evidence" phrase in the quoted question. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-23 0:00 Not intended for use in medical, Robert C. Leif, Ph.D. ` (2 preceding siblings ...) 1997-04-25 0:00 ` Kevin Cline @ 1997-04-28 0:00 ` John Apa 1997-04-28 0:00 ` John M. Mills 1997-04-28 0:00 ` Robert Dewar 3 siblings, 2 replies; 120+ messages in thread From: John Apa @ 1997-04-28 0:00 UTC (permalink / raw) Robert C. Leif, Ph.D. wrote: > > To: Tim Behrendsen, Kaz Kylheku et al. > From: Robert C. Leif, Ph.D. > Vice President Ada_Med {snip} > > This quote may provide an excellent opportunity in the medical device > business, which is NOT puny. My question is, Does validation of an Ada > compiler on a platform provide significant evidence that the processor > produces valid object code? Would any of the other Ada test suites help? > I deliberately used the word significant rather than sufficient. If anyone > knows how to prove sufficiency, I would also like a comment. Any other > suggestions that would permit realistic development of medical devices > would be appreciated. > If it were me designing life support systems for medical use I'd: Make use of Appendix H (Safety and Security) in Ada95. Review the object code. And then test the hell out of it like my life depended on it. Ada95 provides wonderful tools, but it is still up to the engineer to make sure the fnal product does what it is supposed to do. -- *********************************** Standard Disclaimers Apply John Thomas Apa Replace "DIE_SPAMMER" with "delphi" to email. Honeywell Defense Avionics Systems Albuquerque, New Mexico. *********************************** ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-28 0:00 ` John Apa @ 1997-04-28 0:00 ` John M. Mills 1997-04-30 0:00 ` Larry Kilgallen 1997-04-28 0:00 ` Robert Dewar 1 sibling, 1 reply; 120+ messages in thread From: John M. Mills @ 1997-04-28 0:00 UTC (permalink / raw) John Apa <japa@DIE_SPAMMER.dasd.honeywell.com> writes: >Robert C. Leif, Ph.D. wrote: >> To: Tim Behrendsen, Kaz Kylheku et al. >> From: Robert C. Leif, Ph.D. >> Vice President Ada_Med >{snip} >> This quote may provide an excellent opportunity in the medical device >> business, which is NOT puny. My question is, Does validation of an Ada >> compiler on a platform provide significant evidence that the processor >> produces valid object code? Would any of the other Ada test suites help? IMH(non-legal)O, respectively: no, and no. I think these are simply the wrong questions. Based solely on what I've read in this thread, it seems very foolish to even discuss programming language selection in this context. My reading was that Intel, for whatever reason, has served notice that some of their products are inappropriate for an entire class of application in which the likelihood and cost of litigation, as well as typical damage awards, are extremely high [at present in the U.S.A.]. Should someone suffer injury from a medical device based on such a product, and the designer of the device be reasonably expected to have checked the appropriateness of his or her processor selection, I would not wish to be the attorney defending them. Of course there is little risk of that, since I am not an attorney and could not give legal advice. However, I can make a pretty good guess what an attorney would advise such a client while they were making their processor selection: avoid like the plague any components for which the manufacturer has issued a disclaimer of suitability for your product's intended use! Regardless of whether the target processor (and/or the host of a cross- development environment) would produce properly executing code, the processor manufacturer has disclaimed assertion that their processor would _execute_ such code in a proper fashion. The same charges could possibly be made against the target operating system (if any), run-time environment, etc. I am not in sympathy with the approach Intel seems to reflect in their statement, and I suspect it might compromise their defense in any liability action which might arise from use of this processor in a non- medical, life-critical application -- which might include anything from avionics to an emergency-response telephone system (or other processors, as I understand the disclaimer was model-specific and one could ask: "Does Intel thus imply that their 80* _is_ appropriate, and how did they determine so?"). I only point out that this is a barndoor-sized exposure with hugely expensive potential consequences. -- John M. Mills, Senior Research Engineer -- john.m.mills@gtri.gatech.edu Georgia Tech Research Institute, Georgia Tech, Atlanta, GA 30332-0834 Phone contacts: 404.894.0151 (voice), 404.894.6258 (FAX) "Lies, Damned Lies, Statistics, and Simulations" ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-28 0:00 ` John M. Mills @ 1997-04-30 0:00 ` Larry Kilgallen 1997-05-02 0:00 ` Nick Roberts 0 siblings, 1 reply; 120+ messages in thread From: Larry Kilgallen @ 1997-04-30 0:00 UTC (permalink / raw) In article <5k2rlk$hic@acmey.gatech.edu>, jm59@prism.gatech.edu (John M. Mills) writes: > However, I can make a pretty good guess what an attorney would advise such > a client while they were making their processor selection: avoid like the > plague any components for which the manufacturer has issued a disclaimer of > suitability for your product's intended use! DEC machines for a long time had documentation saying they were not for use in controlling nuclear reactors. I tend to believe such a statement reflects not special constraints of the problem domain but rather the size of potential damage awards. Larry Kilgallen ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-30 0:00 ` Larry Kilgallen @ 1997-05-02 0:00 ` Nick Roberts 0 siblings, 0 replies; 120+ messages in thread From: Nick Roberts @ 1997-05-02 0:00 UTC (permalink / raw) Larry Kilgallen <kilgallen@eisner.decus.org> wrote in article <1997Apr29.211810.1@eisner>... > In article <5k2rlk$hic@acmey.gatech.edu>, jm59@prism.gatech.edu (John M. Mills) writes: > > > However, I can make a pretty good guess what an attorney would advise such > > a client while they were making their processor selection: avoid like the > > plague any components for which the manufacturer has issued a disclaimer of > > suitability for your product's intended use! > > DEC machines for a long time had documentation saying they were not > for use in controlling nuclear reactors. I tend to believe such a > statement reflects not special constraints of the problem domain > but rather the size of potential damage awards. > > Larry Kilgallen > Can one imagine a disclaimer such as "this technology is not suitable for use in playing Space Invaders or other extra-terrestrial invasion games programs?" Nick ;-) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-28 0:00 ` John Apa 1997-04-28 0:00 ` John M. Mills @ 1997-04-28 0:00 ` Robert Dewar 1997-04-29 0:00 ` Kaz Kylheku 1 sibling, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-04-28 0:00 UTC (permalink / raw) John said <<If it were me designing life support systems for medical use I'd: Make use of Appendix H (Safety and Security) in Ada95. Review the object code. And then test the hell out of it like my life depended on it.>> This sounds like depending on testing too much, and on formal methods too little -- there is a balance sure, but the above seems unbalanced. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-28 0:00 ` Robert Dewar @ 1997-04-29 0:00 ` Kaz Kylheku 1997-04-30 0:00 ` John Apa ` (2 more replies) 0 siblings, 3 replies; 120+ messages in thread From: Kaz Kylheku @ 1997-04-29 0:00 UTC (permalink / raw) In article <dewar.862270256@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >John said > ><<If it were me designing life support systems for medical use I'd: >Make use of Appendix H (Safety and Security) in Ada95. >Review the object code. >And then test the hell out of it like my life depended on it.>> > >This sounds like depending on testing too much, and on formal methods >too little -- there is a balance sure, but the above seems unbalanced. Reviewing the object code is (or can be) a formal method. Maybe the use of the word ``hell'' shifts the perception of balance. :) It's a pity that this discussion was confined to comp.lang.ada, because I missed a lot of it, even though I sparked it with quote from the Intel document. Reviewing object code is important. I do it all the time, no matter what langauge I'm using. Compiler bugs do exist; I have discovered a few in GNU C. (just read gnu.gcc.bug over some time and you will see). For example, here is one I found myself: /* * Program demonstrating bug in GCC 2.7.2 (i386, -O2 -Wall -ansi) * * Sample output: * * foo(0,5) = 0; bar(0,5) = 0 * foo(1,5) = 1; bar(1,5) = 1 * foo(2,5) = 1; bar(2,5) = 1 * foo(3,5) = 1; bar(3,5) = 1 * foo(4,5) = 1; bar(4,5) = 0 <--- should be same for foo() and bar() * foo(5,5) = 0; bar(5,5) = 0 * foo(6,5) = 0; bar(6,5) = 0 * foo(7,5) = 0; bar(7,5) = 0 * foo(8,5) = 0; bar(8,5) = 0 */ #include <stdio.h> int foo(int x, int y) { return ((x < y) && x++) && ((x < y) && x++); } int bar(int x, int y) { return (x < y) && x++ && (x < y) && x++; } /* * GCC seems to illegaly optimize foo() by factoring the (x < y) * as a common subexpression ignoring the x++ side effect, e.g: * * return ((x < y) && x++) && x++; * * A more complex version of this expression has caused a serious * failure in some of my code. */ int main(void) { int i; for (i = 0; i < 9; i++) printf("foo(%d,5) = %d; bar(%d,5) = %d\n", i, foo(i,5), i, bar(i,5)); return 0; } I readily discovered this problem when my program was behaving oddly, and a thorough code inspection failed to turn up any error in the source. Heck, I've even seen serious bugs in _assemblers_. This is quite surprising, given that an assembler is at most a one-man project lasting several weeks, unless you are doing it _in_ assembly :). I used an assembler once which, under peculiar circumstances, failed to synchronize its two passes. It would insert some padding ``no operations'' in one pass which were not accounted for in its back-patching. All relative references crossing that NOOP, and all absolute references to any labels _after_ the NOOP, were offset by the length of the instruction. Fortunately, this was detected easily. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-29 0:00 ` Kaz Kylheku @ 1997-04-30 0:00 ` John Apa [not found] ` <3367CE1E.5ED1@die_spammer.dasd.honeywell.com> 1997-05-03 0:00 ` Simon Wright 2 siblings, 0 replies; 120+ messages in thread From: John Apa @ 1997-04-30 0:00 UTC (permalink / raw) Kaz Kylheku wrote: > > In article <dewar.862270256@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: > >John said > > > ><<If it were me designing life support systems for medical use I'd: > >Make use of Appendix H (Safety and Security) in Ada95. > >Review the object code. > >And then test the hell out of it like my life depended on it.>> > > > >This sounds like depending on testing too much, and on formal methods > >too little -- there is a balance sure, but the above seems unbalanced. > > Reviewing the object code is (or can be) a formal method. Maybe the > use of the word ``hell'' shifts the perception of balance. :) Yes, perhaps I added emphasis to the wrong part. Formal methods are a great thing if you can get everyone to follow them. To me it seems as if many people talk about it yet few actually follow it. This is bad. A team using a well defined and accepted development process and formal methods can do great things. But it only takes one of the team to "just make a quick fix" and then the fun begins. In any case if my life depended on it, I would still test it beyond what many would consider "acceptable". I have slipped my own schedules in order to do a little extra testing or desk checking when I (or others) felt it was required for safety (life and/or data) purposes. I think we owe our end users that, especially the ones who trust our work to keep their planes in the air. To bad MS didn't feel that way about their products. > > It's a pity that this discussion was confined to comp.lang.ada, because I > missed a lot of it, even though I sparked it with quote from the Intel > document. > snipped a good example -- *********************************** Standard Disclaimers Apply John Thomas Apa Replace "DIE_SPAMMER" with "delphi" to email. Honeywell Defense Avionics Systems Albuquerque, New Mexico. *********************************** ^ permalink raw reply [flat|nested] 120+ messages in thread
[parent not found: <3367CE1E.5ED1@die_spammer.dasd.honeywell.com>]
* Re: Not intended for use in medical, [not found] ` <3367CE1E.5ED1@die_spammer.dasd.honeywell.com> @ 1997-05-01 0:00 ` Kaz Kylheku 0 siblings, 0 replies; 120+ messages in thread From: Kaz Kylheku @ 1997-05-01 0:00 UTC (permalink / raw) In article <3367CE1E.5ED1@die_spammer.dasd.honeywell.com>, John Apa <japa@DIE_SPAMMER.dasd.honeywell.com> wrote: >Kaz Kylheku wrote: >> >> In article <dewar.862270256@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >> >John said >> > >> ><<If it were me designing life support systems for medical use I'd: >> >Make use of Appendix H (Safety and Security) in Ada95. >> >Review the object code. >> >And then test the hell out of it like my life depended on it.>> >> > >> >This sounds like depending on testing too much, and on formal methods >> >too little -- there is a balance sure, but the above seems unbalanced. >> >> Reviewing the object code is (or can be) a formal method. Maybe the >> use of the word ``hell'' shifts the perception of balance. :) > >Yes, perhaps I added emphasis to the wrong part. Formal methods are a >great thing if you can get everyone to follow them. To me it seems as if The trick with formal verification is to ``program by contract''. You identify the weakest preconditions for the operation of every component, and verify that it satisfies the postconditions. Once you verify that a component does the right thing for every valid input, you can verify the higher levels that use the components without again looking into the internals of the previously tested components. The individual tests could be done empirically (set up every possible precondition and execute the component) or they can be done formally (prove that the component arrives at the post-conditions if the pre-conditions are satisfied). I like the language feature in Eiffel which lets you codify pre- and post-conditions, and turn on their verification. The problem is identifying what those conditions are. Ideally, they should be codified in some way so that testing can be automated. I've written code in the past where I simply stated what the conditions were in a comment. That's obviously of little use except in a peer code review. >many people talk about it yet few actually follow it. This is bad. A >team using a well defined and accepted development process and formal >methods can do great things. But it only takes one of the team to "just >make a quick fix" and then the fun begins. > >In any case if my life depended on it, I would still test it beyond what >many would consider "acceptable". I have slipped my own schedules in >order to do a little extra testing or desk checking when I (or others) >owe our end users that, especially the ones who trust our work to keep >their planes in the air. > >To bad MS didn't feel that way about their products. I don't normally use ``MS'' products---I've never touched a Microsoft application such as Word and it's been years since I used DOS---but today I had the rare displeasure of using a communication program under Windows 95. Now they call this a ``platform'', but to me, the word suggests a rigid plate that a man can safely stand on. It turns out I had to reboot the system twice because even though a terminal program called ``Hyperterminal'' that became ``locked up'' was successfully aborted, the system did not release the serial device occupied up by that program. As someone from a UNIX background, I had to laugh. My Linux system at home has no trouble releasing a process' resources no matter how it terminates, and this is a freely distributed operating system written by volunteers. The X server and window manager also let me manipulate the window of a ``hosed up'' process in the usual manner; it turns out that the frozen Hyperterminal window could not be moved, closed or minimized. Incidentally, Hyperterminal froze up when I tried to send a file via Zmodem, but accidentally clicked `OK' without having specified a file name. That's robustness and reliability for you! I am surprised that people are looking to use Ada on this ``platform'', as I can tell by reading this newsgroup. What's the benefit? You might as well code in K&R C without function prototypes. The so-called platform will likely cave under before your program execution reaches the first instance of undefined behavior. It's rather like anchoring a steel-and-concrete house to loose soil. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-04-29 0:00 ` Kaz Kylheku 1997-04-30 0:00 ` John Apa [not found] ` <3367CE1E.5ED1@die_spammer.dasd.honeywell.com> @ 1997-05-03 0:00 ` Simon Wright 1997-05-04 0:00 ` Richard Kenner ` (2 more replies) 2 siblings, 3 replies; 120+ messages in thread From: Simon Wright @ 1997-05-03 0:00 UTC (permalink / raw) kaz@vision.crest.nt.com (Kaz Kylheku) writes: > int foo(int x, int y) > > { > return ((x < y) && x++) && ((x < y) && x++); > } [...] > /* > * GCC seems to illegaly optimize foo() by factoring the (x < y) > * as a common subexpression ignoring the x++ side effect, e.g: > * > * return ((x < y) && x++) && x++; > * > * A more complex version of this expression has caused a serious > * failure in some of my code. > */ [...] > I readily discovered this problem when my program was behaving oddly, and > a thorough code inspection failed to turn up any error in the source. Hmm. I believe that writing eg a[i] = ++i; invokes undefined behaviour (is the pre- or post- value of i used for the index operation?). While inspecting your program, I would be fairly sure of the meaning you intended but quite unsure without checking the standard as to whether it had entered the realm of the undefined. And I see that your original code was _more_ complex! Crikey! I would also wonder why the second ++ was there anyway, it has no effect (unless of course x was a reference, but we're talking C here, and then the effect of the code would be amazingly hard to understand) -- Simon Wright Work Email: simon.j.wright@gecm.com GEC-Marconi Radar & Defence Systems Voice: +44(0)1705-701778 Command & Information Systems Divsion FAX: +44(0)1705-701800 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-03 0:00 ` Simon Wright @ 1997-05-04 0:00 ` Richard Kenner 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Kaz Kylheku 2 siblings, 0 replies; 120+ messages in thread From: Richard Kenner @ 1997-05-04 0:00 UTC (permalink / raw) In article <x7vohassedl.fsf@pogner.demon.co.uk> Simon Wright <simon@pogner.demon.co.uk> writes: >kaz@vision.crest.nt.com (Kaz Kylheku) writes: >> return ((x < y) && x++) && ((x < y) && x++); >Hmm. I believe that writing eg > > a[i] = ++i; > >invokes undefined behaviour (is the pre- or post- value of i used for >the index operation?). That's correct. The statement above is invalid C and the results are undefined since there is a use and post-incremement within the same pair of sequence points. However, the originally-quoted statement is perfectly valid and well-defined because "&&" is a sequence point. GCC was indeed generating the incorrect code for that statement. If I remember correctly, the fix for that bug was installed in the development sources last week sometime. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-03 0:00 ` Simon Wright 1997-05-04 0:00 ` Richard Kenner @ 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Kaz Kylheku 2 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-04 0:00 UTC (permalink / raw) kaz@vision.crest.nt.com (Kaz Kylheku) writes: > int foo(int x, int y) > > { > return ((x < y) && x++) && ((x < y) && x++); > } [...] > /* > * GCC seems to illegaly optimize foo() by factoring the (x < y) > * as a common subexpression ignoring the x++ side effect, e.g: > * > * return ((x < y) && x++) && x++; > * > * A more complex version of this expression has caused a serious > * failure in some of my code. > */ This is an amazingly comon mistake, and people are always sending in bogus bug reports to the gcc list complaining about this particular case. In fact, as Simon points out, an expresson like the above one is entirely undefined, and it is quite clear from the ANSI standard that it is undefined. There is no bug in gcc here, just a bug in the program, and as usual when programmers put bugs into programs it can cause serious failures. The factoring that GCC is doing here is quite legitimate, and indeed it is *precisely* to allow this kind of optimziation that the standard declares expressions like this to have undefined semantics. One important thing that all programmers need to learn is that it is critical if you are trying to write portable code to know the language definition. The fact that something happens to work is NOT proof that your code is correct. It is possible to write completely portable code in many languages, including for example C, COBOL and Fortran, but only if you know the lanuage definition well. In practice, very few C, COBOL or Fortran programmers know the standard well (typical programmers for these languages have not even read the standard). One of the great achievments of Ada 83 was that for the first time since Algol-60, we had a language where typical professional programmers owned the standard, and used it at least as a reference work. Even in Ada 95 this tradition continues (despite the fact that the Ada 95 standard is much less accessible than the Ada 83 standard, due to a decision to attempt to be much more precise -- this is always a tough trade off) Note also that portability is extremely important in contexts that might be surprising (such as turning optimization on or off, going to a new version of the same compiler, or, as in this case, going to a different compiler on the same machine). ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-03 0:00 ` Simon Wright 1997-05-04 0:00 ` Richard Kenner 1997-05-04 0:00 ` Robert Dewar @ 1997-05-04 0:00 ` Kaz Kylheku 1997-05-04 0:00 ` Robert Dewar 2 siblings, 1 reply; 120+ messages in thread From: Kaz Kylheku @ 1997-05-04 0:00 UTC (permalink / raw) In article <x7vohassedl.fsf@pogner.demon.co.uk>, Simon Wright <simon@pogner.demon.co.uk> wrote: >kaz@vision.crest.nt.com (Kaz Kylheku) writes: > >> int foo(int x, int y) >> >> { >> return ((x < y) && x++) && ((x < y) && x++); >> } [ snip ] >Hmm. I believe that writing eg > > a[i] = ++i; > >invokes undefined behaviour (is the pre- or post- value of i used for >the index operation?). Sorry about this C intrusion into comp.lang.ada. I didn't intend that example to spark a discussion about C semantics, but just to clear up, the && operator in C has sequencing properties. Its left constituent must not only be evaluated before its right, but its side effects must also be settled before the left side is evaluated. Hence x++ && x++ is perfectly well defined. The program I was writing depended on this crucial sequencing property. >While inspecting your program, I would be fairly sure of the meaning >you intended but quite unsure without checking the standard as to >whether it had entered the realm of the undefined. And I see that your >original code was _more_ complex! Crikey! The complexity was hidden behind friendly macros. :) The intent was to inline some code which performed external data encoding and decoding, having the logic ``if there is space in the buffer, add a character to it and return true, else return false''. This logic was turned into a function-like macro. The problem arose when I combined two of the macros like this: foo(..) && foo(...) The bounds check in the second case was ``optimized'' away due to the bug, allowing the buffer to be overrun by one character. That bug is there, in GCC 2.7.2., though Chris Torek rapidly came up with a an unofficial patch. :) >I would also wonder why the second ++ was there anyway, it has no >effect (unless of course x was a reference, but we're talking C here, >and then the effect of the code would be amazingly hard to understand) The example you are looking at was specially contrived to illustrate the bug, so it has no useful meaning. When reporting a compiler bug, it's quite helpful to the developers if you can contrive the smallest example which illustrates the bug. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-04 0:00 ` Kaz Kylheku @ 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Richard Kenner 1997-05-05 0:00 ` Kaz Kylheku 0 siblings, 2 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-04 0:00 UTC (permalink / raw) Kaz said <<Sorry about this C intrusion into comp.lang.ada. I didn't intend that example to spark a discussion about C semantics, but just to clear up, the && operator in C has sequencing properties. Its left constituent must not only be evaluated before its right, but its side effects must also be settled before the left side is evaluated. Hence x++ && x++ is perfectly well defined. The program I was writing depended on this crucial sequencing property.>> Yes, legal, but horrible. A good reminder of why Ada does NOT have the ++ operator built in :-) <<The complexity was hidden behind friendly macros. :)>> How can it ever be friendly to hide a ++ in a macro, such that the peculiar rules about not using more than one ++ in an expression suddenly apply in a hidden manner to the macro, Ugh! ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-04 0:00 ` Robert Dewar @ 1997-05-04 0:00 ` Richard Kenner 1997-05-05 0:00 ` Kaz Kylheku 1 sibling, 0 replies; 120+ messages in thread From: Richard Kenner @ 1997-05-04 0:00 UTC (permalink / raw) In article <dewar.862775250@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes: > How can it ever be friendly to hide a ++ in a macro, such that the > peculiar rules about not using more than one ++ in an expression > suddenly apply in a hidden manner to the macro, Ugh! The classic is when you have the common macro: #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) And then forget what the macro expands to and use MIN (a[n++]) someplace. Of course, not only is that particular case undefined, but it might increment N twice. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Richard Kenner @ 1997-05-05 0:00 ` Kaz Kylheku 1997-05-06 0:00 ` Kaz Kylheku 1 sibling, 1 reply; 120+ messages in thread From: Kaz Kylheku @ 1997-05-05 0:00 UTC (permalink / raw) In article <dewar.862775250@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Kaz said > ><<Sorry about this C intrusion into comp.lang.ada. I didn't intend that > example to spark a discussion about C semantics, but just to clear up, > the && operator in C has sequencing properties. Its left constituent > must not only be evaluated before its right, but its side effects must > also be settled before the left side is evaluated. Hence x++ && x++ is > perfectly well defined. The program I was writing depended on this crucial > sequencing property.>> > > Yes, legal, but horrible. A good reminder of why Ada does NOT have > the ++ operator built in :-) > ><<The complexity was hidden behind friendly macros. :)>> > > How can it ever be friendly to hide a ++ in a macro, such that the > peculiar rules about not using more than one ++ in an expression > suddenly apply in a hidden manner to the macro, Ugh! How can it ever be friendly? If you take care to use proper sequencing operations to protect the user from the side effects, as I did. Thus the ``peculiar rules'' were taken care of. In my original macro, the quantities that were compared and incremented were structure members. The only caveat was that the pointer to the structure was evaluated more than once by the macro (the same way that getc() or putc() possibly evaluate the FILE * pointer argument more than once). In any case, these macros were for internal use. There is a more serious snag: if someone naively did something silly like foo() + foo(), undefined behavior could result. Even though both constituents of the + contain the && sequencing operator, the + operator doesn't guarantee a particular order of evaluation. The sequence points in both constituents are independent, so that ((x < y) && x++) + ((x < y) && x++) could, in the actual semantics, evaluate both constituents in an interleaved fashion, perhaps even effectively merging the sequence points into one. God I love this stuff! :) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-05 0:00 ` Kaz Kylheku @ 1997-05-06 0:00 ` Kaz Kylheku 1997-05-06 0:00 ` Robert A Duff 0 siblings, 1 reply; 120+ messages in thread From: Kaz Kylheku @ 1997-05-06 0:00 UTC (permalink / raw) In article <5kl9qc$g4d@bcrkh13.bnr.ca>, Kaz Kylheku <kaz@vision.crest.nt.com> wrote: >In article <dewar.862775250@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >>Kaz said >> >><<Sorry about this C intrusion into comp.lang.ada. I didn't intend that >> example to spark a discussion about C semantics, but just to clear up, >> the && operator in C has sequencing properties. Its left constituent >> must not only be evaluated before its right, but its side effects must >> also be settled before the left side is evaluated. Hence x++ && x++ is >> perfectly well defined. The program I was writing depended on this crucial >> sequencing property.>> >> >> Yes, legal, but horrible. A good reminder of why Ada does NOT have >> the ++ operator built in :-) By the way, the x++ is just another way of writing the assignment expression x += 1, or x = x + 1 (the latter case evaluates x twice, of course). The real ``evil'' perhaps is that in C an assignment is an expression rather than a statement, so that you can decorate a complex expression with assignments all over the place. Note that this is one of the areas of C which C++ _worsens_ significantly. In C++, the result of an assignment expression is not only an expression itself, but it is also an _lvalue_. Talk about lunacy. With one stroke, the C++ ``designers'' introduce a whole new batch of nonsense, such as (i = x) = y; which must be rejected by any conforming C implementation as constraint violation. What's the final value of i? Is it x? Or is it y? My friend, do not waste your time: the behavior's undefined. Better C indeed! :) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-06 0:00 ` Kaz Kylheku @ 1997-05-06 0:00 ` Robert A Duff 1997-05-07 0:00 ` Robert Dewar 1997-05-07 0:00 ` Kaz Kylheku 0 siblings, 2 replies; 120+ messages in thread From: Robert A Duff @ 1997-05-06 0:00 UTC (permalink / raw) In article <5kmek2$9re@bcrkh13.bnr.ca>, Kaz Kylheku <kaz@vision.crest.nt.com> wrote: >>> Yes, legal, but horrible. A good reminder of why Ada does NOT have >>> the ++ operator built in :-) > >By the way, the x++ is just another way of writing the assignment expression x >+= 1, or x = x + 1 (the latter case evaluates x twice, of course). The real >``evil'' perhaps is that in C an assignment is an expression rather than a >statement, so that you can decorate a complex expression with assignments all >over the place. I agree (except I'd remove "perhaps"). There's nothing wrong with having short-hand notations like "++" and "+=". The language design flaw in C is that assignments return something "useful", thus encouraging side effects nested within expressions, like a[i++]. I'm not against *all* kinds of side effects, but I'm against most of them, including the one mentioned above. - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-06 0:00 ` Robert A Duff @ 1997-05-07 0:00 ` Robert Dewar 1997-05-08 0:00 ` John G. Volan ` (2 more replies) 1997-05-07 0:00 ` Kaz Kylheku 1 sibling, 3 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-07 0:00 UTC (permalink / raw) Robert Duff said <<I agree (except I'd remove "perhaps"). There's nothing wrong with having short-hand notations like "++" and "+=".>> There is something potentially wrong, which is that compact operation notations like this are most happy with short identifier names, as in a++; not nearly so pretty is Average_Daily_Rate_Of_Pay++; and indeed if you speak the above, it comes out as a joke, people laugh. Well of course this is not the only reason that C programmers so often favor short cryptic identifier names (and of course there is nothing in C which requires them), but it is a contributing factor! ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-07 0:00 ` Robert Dewar @ 1997-05-08 0:00 ` John G. Volan 1997-05-10 0:00 ` Robert Dewar 1997-05-08 0:00 ` Not intended for use in medical, Robert A Duff 1997-05-08 0:00 ` Kaz Kylheku 2 siblings, 1 reply; 120+ messages in thread From: John G. Volan @ 1997-05-08 0:00 UTC (permalink / raw) Robert Dewar wrote: > > Robert Duff said > > <<I agree (except I'd remove "perhaps"). There's nothing wrong with > having short-hand notations like "++" and "+=".>> > > There is something potentially wrong, which is that compact operation > notations like this are most happy with short identifier names, as in > > a++; > > not nearly so pretty is > > Average_Daily_Rate_Of_Pay++; > > and indeed if you speak the above, it comes out as a joke, people laugh. That's why I've suggested before that an Ada analog to "++" could have been rendered as a procedure attribute: Money_Type'Increment (Average_Daily_Rate_Of_Pay); Far less error prone than: Average_Daily_Rate_Of_Pay := Average_Weekly_Rate_Of_Pay + 1; -- Oops! Ah, if only ... :-) I mean, if T'Min and T'Max could make it into Ada95, then why not: procedure T'Increment (X : in out T); -- ++ analog procedure T'Decrement (X : in out T); -- -- analog procedure T'Increase (X : in out T; By : in T); -- += analog procedure T'Decrease (X : in out T; By : in T); -- -= analog procedure T'Multiply (X : in out T; By : in T); -- *= analog procedure T'Divide (X : in out T; By : in T); -- /= analog Yes, I know these can all be done with ordinary procedures and generics, and I know there's a limit to what you can cram into a language specification. But in this case, I think it would have been politically savvy to have included something like these attributes, as an answer to the challenge from C++'s operators. Well, we've been down this road before. What was that about "wishes and fishes" ...? :-) ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` John G. Volan @ 1997-05-10 0:00 ` Robert Dewar 1997-05-10 0:00 ` John G. Volan 1997-05-12 0:00 ` Language Design Mistakes (was "not intended...") W. Wesley Groleau (Wes) 0 siblings, 2 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-10 0:00 UTC (permalink / raw) <<Yes, I know these can all be done with ordinary procedures and generics, and I know there's a limit to what you can cram into a language specification. But in this case, I think it would have been politically savvy to have included something like these attributes, as an answer to the challenge from C++'s operators.>> Bad reason! It is almost always a mistake in languages to make compromises in the design on the grounds that users of language X won't be happy unless you do. Every time I have seen this done I think it is a mistake. Three examples: In Algol-68 Really we should make people write ref all the time because it is important for people to know that something is a variable, but if we make the normal declaration for an integer variable be: ref int x; Fortran and Algol-60 programmers will never tolerate it, so let's make a special rule -- that the ref is implied here, so we can write: int x; but only in this case, for other declaration forms, the ref is required. Bottom line: confusion, and surprise! Neither Algol-60 nor Fortran programmers like confusion! In Ada 83 (and Ada 95) Really we should declare the type of everything, but Fortran users would never put up with for x in integer range 0 .. 10 loop ... so let's have a special rule that we get a default use of integer here. Similarly, Fortran users will never put up with having to declare all those array types, so let's allow anonymous array declarations: My opinion is that both these decisions are mistakes, they introduce irregularity and confusion. People are not going to say, "Hey, let's use Ada because it has all the goodies we know and love from language X". If that is their viewpoint, there is a language that much more certainly has all the goodies from language X, and that they are much more likely to use. If people switch to a new language it is because they see some general advantages. If they make the switch, they want to find something coherent and well designed when they get there. Features should go in a language because they make sense in terms of the syntactic and semantic framework of the language, not because of some perceived political value. That is especially true of tiny syntactic gizmos. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-10 0:00 ` Robert Dewar @ 1997-05-10 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert Dewar 1997-05-12 0:00 ` Language Design Mistakes (was "not intended...") W. Wesley Groleau (Wes) 1 sibling, 1 reply; 120+ messages in thread From: John G. Volan @ 1997-05-10 0:00 UTC (permalink / raw) I (John Volan) wrote: [*] > > But in this case, I think it would have been politically > savvy to have included something like these attributes, as an answer to > the challenge from C++'s operators. Robert Dewar replied: [*] > > Bad reason! It is almost always a mistake in languages to make compromises > in the design on the grounds that users of language X won't be happy unless > you do. John Volan replies: I will grant you that a language feature cannot be justified _solely_ on political grounds, it has to have enough utility in its own right to outweigh the cost of the added complexity. In this case, however, I believe T'Increment and so forth _would_ have had merit in their own right, irrespective of any analogy they might bear to C++ side-effect operators. As I pointed out, they'd help avoid unnecessary and error-prone repetition of variable names in certain common cases of arithmetic statement, and I believe they'd thereby enhance readability. > Every time I have seen this done I think it is a mistake. Three > examples: [snip good examples of bad language compromises] In each of these cases, a general design principle in language X was compromised to introduce a specific exceptional case, with the only justification being that it was politically necessary to make that special case resemble language Y. But I don't see how any of these are an analogy to T'Increment, etc. How would these be special exceptional cases of attributes? I don't see how they'd "compromise" any of Ada's design principles at all. Now, if I had suggested that these be _functions_ that caused side effects but also returned values or (shudder, shudder) returned "references" to variables, then that truly would have "compromised" Ada's design. Likewise if I had suggested, as others have, that we introduce new side-effect delimiters, e.g. "+:=", "-:=", "*:=" etc. But I suggested nothing of the sort. In fact, these attribute procedures would be no different in kind from any other attribute subprogram already present in Ada95. Consider T'Min and T'Max. Why were they added, when their functionality could easily have been supplied with a generic? In fact, it could have been just another generic child of package Ada. Why aren't T'Ceiling, T'Floor, and the like just more functions in Ada.Numerics.Generic_Elementary_Functions? It can't be because they are somehow "intrinsic", because of course intrinsicness can be supplied by a pragma. No, the reason they're all attributes rather than generics is because they are extremely convenient to have at the tip of your fingers. (I assume that was also the motivation for GNAT's non-standard attributes, e.g. X'Img). The reason for not having included T'Increment etc. could only have been either (1) nobody brought up the issue, or (2) well, it was getting late, and heck we had to draw the line _somewhere_. If so, then fair enough. > Features should go in a language because they make sense in terms of the > syntactic and semantic framework of the language, not because of some > perceived political value. That is especially true of tiny syntactic > gizmos. I agree, but having said all that, you can't _entirely_ ignore politics when designing a language, not it today's climate. And in fact, the design of Ada95 certainly did not (_could_ not) ignore politics. Case in point: tagged types. A _huge_ new "gizmo", adding a whole new layer of complexity to the language. It has been argued several times (and most recently in an article in the March/April 1997 Ada Letters) that tagged type inheritance -- in fact, derived type inheritance in general -- compromises one of the original design principles of Ada: locality of declaration. If a package declares a derived type, you cannot simply look at that package and know what record components and primitive subprograms are defined for that type. You also have to hunt down the package that declares the base type, and look at its components and primitives. If that base type was derived from something else, you have to hunt down _that_ package too, and so on. And if you do classwide programming and get dynamic dispatching, then it's no longer true that you can just look at a subprogram call and know exactly what code is getting invoked. All of these things, if abused, can be detrimental to the goals of software engineering and real-time embedded programming. So why do we have inheritance in Ada95? Because, quite simply, it was perceived by many that Ada9X would be doomed to utter extinction if it did not become a fully object-oriented language. Large constituencies in the computer industry would simply reject it out of hand. (_I_ would have rejected it, and if you know me, that's saying a lot.) Now, at least, Ada95 stands a fighting chance. Isn't it obvious that the decision to add type extension and OO-style inheritance was at least _partly_ political? [*] P.S. Robert, your unconventional quoting style forced me to tease out and re-attribute my own words. Doesn't your newsreader/email program support good old standard ">" quotations? You yourself have argued the benefits of adhering to widely-established conventions, why make an exception here? (Although I will admit, it does allow me to tell at a glance that you are the author of a given post, which I suppose is a nice convenience... :-) ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-10 0:00 ` John G. Volan @ 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` John G. Volan ` (3 more replies) 0 siblings, 4 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-11 0:00 UTC (permalink / raw) John said <<Ada.Numerics.Generic_Elementary_Functions? It can't be because they are somehow "intrinsic", because of course intrinsicness can be supplied by a pragma. No, the reason they're all attributes rather than generics is because they are extremely convenient to have at the tip of your fingers. (I assume that was also the motivation for GNAT's non-standard attributes, e.g. X'Img). Partly that, and partly because they correspond to the generic primitive functions standard, and also in many cases to the IEEE required operations. <<The reason for not having included T'Increment etc. could only have been either (1) nobody brought up the issue, or (2) well, it was getting late, and heck we had to draw the line _somewhere_. If so, then fair enough.>> No, I think it is just that they seem to junky, at least in this form. Certainly for instance the notion of "Increment" is inappropriate for enumeration types. I personally prefer NOT to see T'Increment and T'Decrement added, and would not find these sufficiently attractive additions to be worth the extra complexity. So both of the reasons you guess are wrong -- it is simply that people do not agree with you that these would have been worth while additions! <<So why do we have inheritance in Ada95? Because, quite simply, it was perceived by many that Ada9X would be doomed to utter extinction if it did not become a fully object-oriented language.>> This is just wrong, you like to guess about things, but you were not there, and so it is not surprising that your guesses bear little relationship to reality. One of the things that is becoming generally agreed in programming languages is that you need both genericity (for parametrized abstractions) and inheritance (for extensible abstractions. Ada 83 had one and not the other, so providing the other is clearly technically a good idea, and indeed was in the requirements document for Ada 95. As one of the authors of that document, I can assure you that the primary motivation for adding full inheritance in Ada 95 was that we felt there was a strong justifiable technical need for these features. Yes, this coincides with political pressures from some quarters, but to think of these features as being the result of these political pressures is backwards. The reason for the political pressures was the widespread technical perception of the importance of extensible abstractions. This same widespread *technical* perception is what lead to the inclusion of these features. <<Case in point: tagged types. A _huge_ new "gizmo", adding a whole new layer of complexity to the language. It has been argued several times (and most recently in an article in the March/April 1997 Ada Letters) that tagged type inheritance -- in fact, derived type inheritance in general -- compromises one of the original design principles of Ada: locality of declaration.>> Yes, of course these arguments are very familiar, they are the arguments that were used in excluding general inheritance from Ada 83 in the first place (remember that the Ada 83 design team was very familiar with object oriented programming, since they had done extensive programming in Simula-67 [C++ did NOT invent OO, despite some people's illusions to the contrary :-)] However, the fact is that the requirements document rejects these arguments, as did the majority of those involved with the Ada 9X design. Jean Ichbiah strongly supported the addition of OO facilities to the language in the context of the redesign of the language for example. Your attempt to create the notion that lots of people opposed these ideas, but they got put in anyway because of political pressure simply bares no relation to what actually happened! <<[*] P.S. Robert, your unconventional quoting style forced me to tease out and re-attribute my own words. Doesn't your newsreader/email program support good old standard ">" quotations? You yourself have argued the benefits of adhering to widely-established conventions, why make an exception here? (Although I will admit, it does allow me to tell at a glance that you are the author of a given post, which I suppose is a nice convenience... :-)>> My environment does not nicely support the > convention for many reasons, not least of which is that I cannot rewrap things easily. I am following the quoting suggestion that Norm Cohen made, and I find it solves many problems P.S. going back to 'Max and 'Min, I find these tolerable, though unnecessary additions to Ada 83. If you tell me that your view is that if I have Min and Max, then I should also have all yoru extra attributes, then I would prefer to have none of them. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar @ 1997-05-11 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert A Duff 1997-05-11 0:00 ` John G. Volan ` (2 subsequent siblings) 3 siblings, 1 reply; 120+ messages in thread From: John G. Volan @ 1997-05-11 0:00 UTC (permalink / raw) Robert Dewar wrote: > > No, I think it is just that they seem to junky, ... I hope this is not just a case of "guilt by association." I seem to recall that those "+:=" operators were proposed during the Ada9X process, and I agree those did seem quite "junky". But I've tried to distinguish T'Increment etc. from those. T'Increment might be _analogous_ to "+:=", but I hope I've made it clear how it would be safer, and more "natural" for Ada. > ...at least in this form. Hmm. What form would make them seem less "junky" to you? > Certainly for instance the notion of "Increment" is inappropriate for > enumeration types. I can't see why. It seems plain to me that to "increment" a variable would mean to assign it the "successor" of its current value, whatever that happens to mean. Since enumeration types have a well-defined meaning for the notion of "successor" and "predecessor", and built-in support for that notion already (T'Succ and T'Pred), there shouldn't be any difficulty there. Perhaps the word "increment" has some different connotation for you (e.g., "Why, John, it just means "add 1" doesn't it? Come now, how can you "add 1" to an enumeration! Don't be so silly...") If the only problem is the label I've affixed to the concept, then perhaps a different one could be found. (Perhaps just overload T'Succ and T'Pred as procedures?) Certainly T'Increase(X, By => <amount>) and T'Decrease(X, By => <amount>) would _not_ be defined for enumeration types, since these would be implemented in terms of "+" and "-", which of course are not part of the abstraction for enumerations. Now, where someone could have difficulty accepting T'Increment and T'Decrement would be for the case of floating and fixed point types, for the same reason that they might have trouble with T'Succ and T'Pred for those types. As you know, Ada83 did not include T'Succ and T'Pred for real types, presumably because there can be no notion of "successor" and "predecessor" for actual mathematical real numbers, because between any two reals there is always an infinity of other reals. But now Ada95 has come up with meanings for T'Succ and T'Pred for floating and fixed point types: for fixed they add/subtract small; for floating they return the machine number immediately above/below; loosely speaking, they return the next representable value greater/lesser than the argument. A mathematical purist would (rightly) scoff at this idea and call it "junky". But a computer programmer should take to this notion readily because...well, let's face it, computers _are_ "junky" in this regard. They have trouble representing infinity. We have to make compromises: floating and fixed-pointe types are only _approximations_ of true mathematical real numbers. They can only represent a finite number of points on the real number line. Well, the notion of being able to get the next "representable" value, given our compromise with infinity, turns out to be an extremely useful one from a practical point of view. Hence, T'Succ and T'Pred for real types. > I personally prefer NOT to see T'Increment and > T'Decrement added, and would not find these sufficiently attractive > additions to be worth the extra complexity. Oh, come now, how much extra "complexity" would it be? How much complexity did T'Min and T'Max add? T'Min is essentially just: function T'Min (Left, Right : T'Base) return T'Base is begin if Left < Right then return Left; else return Right; end if; end T'Min; (well, obviously not literally so, but you know what I mean). And T'Increment would simply be: procedure T'Increment (Arg : in out T'Base) is begin Arg := T'Succ(Arg); end T'Increment; That doesn't seem like a whole lot of complexity to me... > So both of the reasons > you guess are wrong -- it is simply that people do not agree with > you that these would have been worth while additions! I can accept that -- although I'm not sure who you mean by "people". The "people" haven't said much on this subject lately, so I don't know whether they'd agree with me or not. :-) But as for those who had decision-making power during the Ada9X process, if this was presented to them and they rejected it, I'd have to think it was just a matter of taste: Somehow, T'Min and T'Max suited the taste of those with the votes, and somehow T'Increment etc. didn't. (_If_ it ever happened. Did anyone propose standard attribute procedures (or even just standard procedures) as an alternative to the "+:=" proposal during the Ada9X process?) Bottom line, I just can't see any _technical_ distinction between T'Min, T'Max, and T'Increment, etc. > P.S. going back to 'Max and 'Min, I find these tolerable, though unnecessary > additions to Ada 83. If you tell me that your view is that if I have Min > and Max, then I should also have all yoru extra attributes, then I would > prefer to have none of them. Right. All of these attributes can be composed out of elements already present in the language, so in a sense they are "unnecessary". Don't get me wrong, T'Min and T'Max are nice to have. But when I noticed them in the RM, I was puzzled how they managed to slip under the door, given the pressure to keep down the creeping featurism. But I happen to be of the opinion that T'Increment, etc. are a little more than "nice to have" features. As I've already said, I think they're in the category of "not strictly necessary but enhancing readability and error-avoidance," worthy goals in keeping with the design philosophy of Ada. T'Increment, etc. also happen to be analogous to (but much safer than) certain very popular built-in operations at the immediate disposal of C and C++ programmers. They also seem to be analogous to certain perfectly reasonable, safe, and useful operations in other languages, notably COBOL's "ADD 1 TO X". (I think there's something similar in Lisp, but my old Lisp textbook is in a box somewhere...) The absense of analogs to these operations in Ada95 seems to me a challenge to Ada's acceptability (though admittedly a small one) to programmers coming to Ada for the first time from other languages. I don't think in today's climate Ada can afford to live in an ivory tower and eschew _all_ concerns of a "political" or (shudder, shudder) "marketing" nature. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` John G. Volan @ 1997-05-11 0:00 ` Robert A Duff 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` John G. Volan 0 siblings, 2 replies; 120+ messages in thread From: Robert A Duff @ 1997-05-11 0:00 UTC (permalink / raw) In article <3375EBA0.777A@sprintmail.com>, John G. Volan <johnvolan@sprintmail.com> wrote: >Right. All of these attributes can be composed out of elements already >present in the language, so in a sense they are "unnecessary". Don't >get me wrong, T'Min and T'Max are nice to have. But when I noticed them >in the RM, I was puzzled how they managed to slip under the door, given >the pressure to keep down the creeping featurism. You're right -- T'Min and T'Max only barely made it into the language. It's one of those features that have a very small benefit, and a very small cost (in terms of added complexity and so forth). And that combination quite often causes huge arguments about whether the cost/benefit ratio is good enough. By the way, if you want your "T'Increment" feature to fit in with the style of Ada, it should be T'Incr or T'Inc. Attribute names are often abbreviated -- e.g. T'Max, T'Val, T'Pred. I'd say Ada's style is to abbreviate attribute names when you can come up with a "tasteful" abbreviation. - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert A Duff @ 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` John G. Volan 1 sibling, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-12 0:00 UTC (permalink / raw) Robert Duff said <<You're right -- T'Min and T'Max only barely made it into the language. It's one of those features that have a very small benefit, and a very small cost (in terms of added complexity and so forth). And that combination quite often causes huge arguments about whether the cost/benefit ratio is good enough.>> One thing here is to compare if A > B then longname := A; else longname := B; end if; with longname := longname + 1; and look at the substitutions: longname := x'Max (A,B); x'Incr (longname); note that in either case we are adding the type name to the syntax. It sure looks like the argument for syntactic sugar is far stronger in the Max case than the Incr case, this gets even more so if you consider: Func (X'max (a,b), Y'max (c,d)); where the unsugared version is declare temp1 : x; temp2 : y; begin if a > b then temp1 := a; else temp1 := b; end if; if c > d then temp2 := c; else temp2 := d; end if; Func (temp1, temp2); end; The fact that we do not have a conditional expression form in Ada makes the sweetness of the Max/Min sugar noticable. In Algol-68, we have no max or min, but we can write Func ((a > b | a | b), (c > d | c | d)); which is not too awful, and of course you have a similar notation in C. So this should explain why the argument is bogus (the argument that says "hey, you have Max/Min, so why not Incr/Decr). i ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert A Duff 1997-05-12 0:00 ` Robert Dewar @ 1997-05-12 0:00 ` John G. Volan 1 sibling, 0 replies; 120+ messages in thread From: John G. Volan @ 1997-05-12 0:00 UTC (permalink / raw) Robert A Duff wrote: > > By the way, if you want your "T'Increment" feature to fit in with the > style of Ada, it should be T'Incr or T'Inc. That will only work if you don't need to distinguish "Increment" (++ analog) from "Increase(By)" (+= analog). When we had this discussion before on comp.lang.ada, I think there was some criticism against overloading "Inc" and "Dec": procedure T'Inc (X : in out T'Base); -- ++ analog procedure T'Dec (X : in out T'Base); -- -- analog procedure T'Inc (X : in out T'Base; By : in T'Base); -- += analog procedure T'Dec (X : in out T'Base; By : in T'Base); -- -= analog Hence my differentiating Increment vs. Increase, Decrement vs. Decrease. > Attribute names are often > abbreviated -- e.g. T'Max, T'Val, T'Pred. But not always: T'Ceiling (vs. T'Ceil), T'Rounding (vs. T'Rnd), etc. > I'd say Ada's style is to > abbreviate attribute names when you can come up with a "tasteful" > abbreviation. Oh? When I've taught Ada83 in the past, I was always somewhat embarrassed by the fact that there just is no polite pronunciation for 'Succ. :-) ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` John G. Volan @ 1997-05-11 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert Dewar 1997-05-12 0:00 ` John G. Volan 1997-05-12 0:00 ` Not intended for use in medical, John G. Volan 3 siblings, 1 reply; 120+ messages in thread From: John G. Volan @ 1997-05-11 0:00 UTC (permalink / raw) Sigh, it occurred to me that, in the time we've spent bantering over T'Increment, you (Robert) could have already implemented them in GNAT. (Or I could have, if I add in all the time I wasted bantering over it in the past. :-) ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` John G. Volan @ 1997-05-11 0:00 ` Robert Dewar 0 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-11 0:00 UTC (permalink / raw) JOhn Volan says <<Sigh, it occurred to me that, in the time we've spent bantering over T'Increment, you (Robert) could have already implemented them in GNAT. (Or I could have, if I add in all the time I wasted bantering over it in the past. :-)>> Of course we could, they would be trivial to implement, but just because something is trivial to implement is not a good enough reason to include it in the language design *or* add it as an implentation defined attribute ... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` John G. Volan 1997-05-11 0:00 ` John G. Volan @ 1997-05-12 0:00 ` John G. Volan 1997-05-12 0:00 ` Robert Dewar 1997-05-17 0:00 ` Robert I. Eachus 1997-05-12 0:00 ` Not intended for use in medical, John G. Volan 3 siblings, 2 replies; 120+ messages in thread From: John G. Volan @ 1997-05-12 0:00 UTC (permalink / raw) Robert Dewar wrote: > > John said > > <<It has been argued several times > (and most recently in an article in the March/April 1997 Ada Letters) > that tagged type inheritance -- in fact, derived type inheritance in > general -- compromises one of the original design principles of Ada: > locality of declaration.>> > > Yes, of course these arguments are very familiar, they are the arguments > that were used in excluding general inheritance from Ada 83 in the first > place [snip...] > > However, the fact is that the requirements document rejects these > arguments, as did the majority of those involved with the Ada 9X > design. Jean Ichbiah strongly supported the addition of OO facilities > to the language in the context of the redesign of the language for > example. Well that is nice to know! I thought I read somewhere that Jean Ichbiah was resistant to some of those changes. > Your attempt to create the notion that lots of people opposed > these ideas, but they got put in anyway because of political pressure > simply bares no relation to what actually happened! Looks like I read too much into that article in Ada Letters. I got the impression that there is still a significant constituency in the real time industry with serious reservations about OO-style inheritance. Hopefully, it's a dwindling minority. But, to do them justice, we can address their concerns thus: Patient: "Doc, it hurts when I do this." Doctor: "Well, then don't do that!" In other words, tagged types and type derivation are useful tools that have their place, but they are not necessarily the right tool for every problem, and you are not necessarily forced to use them for everything. Make an informed engineering decision, weigh the trade-offs: If the overhead and dynamic dispatching and the indeterminacy of abstract types are unacceptable to a real-time application, just don't use those features. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` John G. Volan @ 1997-05-12 0:00 ` Robert Dewar 1997-05-17 0:00 ` Robert I. Eachus 1 sibling, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-12 0:00 UTC (permalink / raw) John Volan says <<Looks like I read too much into that article in Ada Letters. I got the impression that there is still a significant constituency in the real time industry with serious reservations about OO-style inheritance. Hopefully, it's a dwindling minority.>> It is a significant minority (including for example the authors of the C++ standard template library), and it is not confined to the real time industry (and by the way, you can include me in that minority), but you are right, the Doc/Patient dialog is quite appropriate. No one forces you to use anything in Ada. You like Ada tasks? use them, you don't, then don't use them (just to take another example, I used to say: Ada tasking is a tool, not a rule You can substitute all sorts of other words for tasking in this statement ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` John G. Volan 1997-05-12 0:00 ` Robert Dewar @ 1997-05-17 0:00 ` Robert I. Eachus [not found] ` <dewar.863877808@merv> 1 sibling, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-17 0:00 UTC (permalink / raw) In article <3376CF85.3E15@sprintmail.com> "John G. Volan" <johnvolan@sprintmail.com> writes: > Well that is nice to know! I thought I read somewhere that Jean > Ichbiah was resistant to some of those changes. Jean Ichbiah was concerned about the syntax, not the addition of the features. Incidently, Jean was right that his syntax was "cleaner" or looked better, but Tucker's notation was more useful because it allowed (eventually) the separation of concepts which are hopelessly confused in other OO languages. The vote on the issue reflected this, was it 2-2 with five abstentions? (Hmmm. I think that the US abstained with the announced intent of changing to the winning side, so the final was 3-2-4.) In any case, a close decision on a very subtle issue. Incidently, Tucker did make some changes in response to Jean's issues, and the final result is probably better than either original proposal. > In other words, tagged types and type derivation are useful tools > that have their place, but they are not necessarily the right tool > for every problem, and you are not necessarily forced to use them > for everything. Make an informed engineering decision, weigh the > trade-offs: If the overhead and dynamic dispatching and the > indeterminacy of abstract types are unacceptable to a real-time > application, just don't use those features. Ah, wonderful. In the same post I get to explain the confusions that Ada 95 allows you to sort out. Tagged types and type derivation are perfectly useable in contexts like real-time in Ada 95 with no penalty. It is only when a call actually dispatches at run-time when you need to have a concern. But if your Ada program has no objects declared to be classwide (i.e. Bar: Foo'Class;), then no run-time dispatching will occur. In Ada 95 an abstract type is one which for which no objects can be created. An abstract function is one that can never be called. An abstract data type can be implemented as a classwide type so you get run-time dispatching, and you can declare objects to be members of an abstract class. But in Bar: Foo'Class; where Foo is an abstract type, Bar can never be of type Foo, even though it will always have a type that is derived (directly or indirectly) from Foo. Got it? -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
[parent not found: <dewar.863877808@merv>]
* Re: Not intended for use in medical, [not found] ` <dewar.863877808@merv> @ 1997-05-17 0:00 ` Robert Dewar 1997-05-17 0:00 ` Jon S Anthony 0 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-17 0:00 UTC (permalink / raw) Robert Eachus said << Jean Ichbiah was concerned about the syntax, not the addition of the features. Incidently, Jean was right that his syntax was "cleaner" or looked better, but Tucker's notation was more useful because it allowed (eventually) the separation of concepts which are hopelessly confused in other OO languages. The vote on the issue reflected this, was it 2-2 with five abstentions? (Hmmm. I think that the US abstained with the announced intent of changing to the winning side, so the final was 3-2-4.) In any case, a close decision on a very subtle issue. Incidently, Tucker did make some changes in response to Jean's issues, and the final result is probably better than either original proposal.>> This misremembers the history (as you will remember, I was very much involved in this discussion). I am not sure whether Robert was present at all the DR meetings that lead up to this, I think not ... The initial issue was Jean's concern that "tagged" is a strange word and that we should use "class" instead. This was really as much a concern about using familiar terminology, rather than any purely technical concerns. Indeed from a purely technical point of view, avoiding class, with its baggage from C++ has some advantages. Tuck strongly opposed this change, focussing purely on the technical aspects. The DR's overwhelmingly agreed, and voted by a large margin to make the change, despite Tuck's objections. BUT, and this is a big BUT, they did NOT agree on a syntax. Jean wanted class type x is ... but even some of those strongly supporting the idea of changing the word were opposed to this prefix notation, and the issue of what syntax to use was left open. So the DR decision was clear: change tagged to class, and look for a good syntax. And we left the matter up to Salem (where Robert Eachus was present). At Salem, Tuck gave a long and impassioned defence of tagged, and Jean gave a long and impassioned argument for not just class, but class AND the prefix syntax above. This was of course a serious tactical mistake, but Jean felt he was right, and insisted on presenting these together. Mostly, the delegations were annoyed by the huge amount of effort that had been spent on this relatively unimportant (as they saw it) issue, especi9ally by the mapping team, and that mostly explains the large number of abstentions (the vote was 2-2-4). However, it did not entirely explain the abstentions. At least one delegation in particular *strongly* favored class over tagged, but did not like the prefix notation. They reacted by abstaining, hoping that we could still get class without the prefix notation. That was of coruse a tactical error on their part, the proper thing to achieve their aim would be to have followed along with the proposal, and then look for a better syntax in the aftermath. It is clear that if the vote had been taken again with a bit better understanding, that this delegation would have voted yes, giving 3-2-3. The US delegation abstained, on the grounds that this was the best syntehsis of the opinions of the design team (and Tuck), and other members of the US delegation who strongly favored changing tagged to class. I was the one who suggested that we join the winning side, which ever it was, on the grounds that either way, the best thing was to have a clear as possible decision. Since this was a vote to CHANGE something, a tie fails, and consequently the US delegation voted against to make this decision clear. Many people still feel this decision was a mistake. Tagged is an odd word, and it is awkward when people ask if Ada has classes to have to mumble a bit. But in retrospect it is relatively unimportant, and I ssympathize with the delegations who abstained because they felt too much fuss was being made over a minor issue (incidentally, I am not guessing at this dynamic, several people got up after the vote to present rather angry opinions that we were wasting a lot of time on a trivial issue). This was indeed one of the more contentious points in the history of the development of the Ada 95 design -- any language design goes through debates of this kind. What is remarkable is that the final result in the Ada 95 case was that the standard was approved unanimously (by the delegations that had been involved in the discussions, I believe there were a couple of abstentions from official members who had never been heard from or seen). To me that is a significant achievment. Yes, we had lots of disagreements as we went along, not the least of which was the fundamental tension between trying to keep the changes small and managable from an implementation point of view, and adding all sorts of wonderful features. But in the end, we syntehsized a result that all of us were comfortable with. To me, this was technical discussion and cooperation working in the best possible way. Lots of different opinions, but everyone listening to everyone else, and working hard together to take the best of everyones input. Robert Dewar ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-17 0:00 ` Robert Dewar @ 1997-05-17 0:00 ` Jon S Anthony 1997-05-21 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Ben Brosgol 0 siblings, 1 reply; 120+ messages in thread From: Jon S Anthony @ 1997-05-17 0:00 UTC (permalink / raw) In article <dewar.863880940@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes: > Many people still feel this decision was a mistake. Tagged is an odd word, > and it is awkward when people ask if Ada has classes to have to mumble a > bit. But in retrospect it is relatively unimportant, and I ssympathize As long as we are on about this sort of stuff, do you recall what the reason was for using the "record" syntax with tagged types? Again, not a big deal, but it seems kinda odd. Why not simply: type T is tagged ... end T; type C is new T with ... end C; type D is new T with null; Why the "record" syntax. Especially since tagged types are more different from records than similar (extensible, dispatchable primitive ops, maintain composability of user defined equal, ...) /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-17 0:00 ` Jon S Anthony @ 1997-05-21 0:00 ` Ben Brosgol 1997-05-20 0:00 ` Matthew Heaney [not found] ` <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net> 0 siblings, 2 replies; 120+ messages in thread From: Ben Brosgol @ 1997-05-21 0:00 UTC (permalink / raw) Jon S Anthony wrote: > > As long as we are on about this sort of stuff, do you recall what the > reason was for using the "record" syntax with tagged types? Again, > not a big deal, but it seems kinda odd. Why not simply: > > type T is tagged > ... > end T; > > type C is new T with > ... > end C; > > type D is new T with null; > > Why the "record" syntax. Especially since tagged types are more > different from records than similar (extensible, dispatchable > primitive ops, maintain composability of user defined equal, ...) I don't recall that a proposal for the syntax type T is tagged ... end T; type T1 is new T with ... end T1; was ever discussed during the Ada 9X design. If the idea had come up, then the more likely syntax would have been type T is tagged ... end tagged; for consistency with record types. But then the derivation syntax would look odd: type T1 is new T with ... end tagged; -- Yecch The types whose declarations repeat the type identifier after the "end" are types that use the prefix notation, namely the task types and protected types: task type T1 is ... end T1; protected type T2 is ... end T2; As Robert Dewar mentioned in an earlier article, the subject of "prefix notation" for the OOP types, in particular Jean Ichbiah's proposal class type T is ... end T; did come up during the November 1992 WG9 meeting in Salem, Mass., but it was defeated. The requirement that underlay the OOP enhancements was "programming by extension", and Tucker and the design team looked at the Ada 83 type categories for which this concept made sense. Record types were an obvious candidate, and if you want a record type to be extended, then including the "record" reserved word in the type declaration seems fairly natural. (There was also at one point a proposal to allow extending enumeration types, but this was considered to be more a "nice to have" than an essential feature, and it did not make it into the language.) In any event, tagged types do share a number of properties with record types (such as component selection, aggregate notation, provision for discriminants), so using the "tagged record" syntax is not so strange. Ben Brosgol brosgol@aonix.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-21 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Ben Brosgol @ 1997-05-20 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Jon S Anthony 1997-05-21 0:00 ` Syntax for tagged record types and class types Mats Weber [not found] ` <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net> 1 sibling, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-20 0:00 UTC (permalink / raw) In article <33828299.2A3@world.std.com>, brosgol@world.std.com wrote: >As Robert Dewar mentioned in an earlier article, the subject of "prefix >notation" for the OOP types, in particular Jean Ichbiah's proposal > class type T is ... end T; >did come up during the November 1992 WG9 meeting in Salem, Mass., but it >was defeated. >In any event, tagged types do share a number of properties with record >types (such as component selection, aggregate notation, provision for >discriminants), so using the "tagged record" syntax is not so strange. I'm not dogmatic about the "pure" object-oriented syntax, ie declare O : T; begin O.Op (A); end; though I do think it's pretty hip. What would be cool is to have a selector abstraction, to give you that for free, ie type Stack is ...; selector Top (S : Stack) return Item; So that I could do this: declare The_Stack : Stack; begin The_Item := The_Stack.Top; ... It would be cool to give the programmer control of selection, not unlike what C++ programmers get with references. What would be really cool is to have the compiler treat a selector "invokation" that same as if it were a reference to a record component. That way I could say The_Stack.Top := 5; instead of Update_Top (The_Stack, To => 5); The idea is to let the compiler do the automatic defereferencing (a selector "invokation" could be an lvalue or an rvalue): The_Stack.Top := The_Stack.Top + 1; It's always bothered me a bit (and Bertrand Meyer, too; read his book) that the syntax for selecting an unencapsulated (public) component has to be different from selecting an encapsulated one. The_Stack.Top vs. Top (The_Stack) Especially since we've sort of made this statement that tagged types are "really" records, it would be cool to take the analogy a step farther, by making component selection uniform. While we're at it, maybe we can throw in real constructors, too. We can solve the "problem" with limited types, by allowing a constructor to be called in the declarative region. That way limited types wouldn't have to be definate, or go on the heap unnecessarily. It seems that in Ada 83 design, selectors and constructors, known as "transfer functions," were treated literally as functions. But this confuses initialization (or "binding") with assignment, removing the programmer's ability to initialize a limited object properly (defined as "in the declarative region," or "during the object's elaboration"). -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-20 0:00 ` Matthew Heaney @ 1997-05-21 0:00 ` Jon S Anthony 1997-05-21 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Syntax for tagged record types and class types Mats Weber 1 sibling, 1 reply; 120+ messages in thread From: Jon S Anthony @ 1997-05-21 0:00 UTC (permalink / raw) In article <mheaney-ya023680002005972314260001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > What would be really cool is to have the compiler treat a selector > "invokation" that same as if it were a reference to a record component. > That way I could say > > The_Stack.Top := 5; This is similar to the issue of allowing function results to be L-values. I'm not entirely sure why this was considered a "bad" thing (there's been many occasions I've seen where this would be nice). At the moment it is prevented for at least the reason that function results are considered to be _constant_ objects. > While we're at it, maybe we can throw in real constructors, too. We can > solve the "problem" with limited types, by allowing a constructor to be > called in the declarative region. That way limited types wouldn't have to > be definate, or go on the heap unnecessarily. That's more or less what Limited_Controlled gives you. You can "pass parameters" to Initialize via discriminants. You can also play the "rename the function result" game for limited types (which I think is actually pretty nice) and that does what you want as well. /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-21 0:00 ` Jon S Anthony @ 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Robert I. Eachus 1997-05-23 0:00 ` Jon S Anthony 0 siblings, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-21 0:00 UTC (permalink / raw) In article <JSA.97May21160340@alexandria>, jsa@alexandria (Jon S Anthony) wrote: >That's more or less what Limited_Controlled gives you. You can "pass >parameters" to Initialize via discriminants. You can also play the >"rename the function result" game for limited types (which I think is >actually pretty nice) and that does what you want as well. I think that using discriminants as "constructor arguments" is a real kludge, and obfuscates declarations. Ada 95 doesn't have constructors, so let's not try to fight the language. Here is what I'd like to do: declare The_File : File_Type'Open (Name => "my_file.dat", Mode => In_Mode); begin Renaming a function return as a constant object won't fly, because I have to modify the object. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-21 0:00 ` Matthew Heaney @ 1997-05-22 0:00 ` Robert I. Eachus 1997-05-25 0:00 ` Matthew Heaney 1997-05-23 0:00 ` Jon S Anthony 1 sibling, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-22 0:00 UTC (permalink / raw) In article <mheaney-ya023680002105972302430001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > Here is what I'd like to do: > declare > The_File : File_Type'Open (Name => "my_file.dat", Mode => In_Mode); > begin > Renaming a function return as a constant object won't fly, because > I have to modify the object. Ada works the same as C and C++ here, but the notation is different. Adding the Ada style of naming a type whenever possible you get: package New_IO is type File_Type is limited private; type File_Access is access all New_IO.File_Type; ... end New_IO; declare The_File: New_IO.File_Access := New_IO.Open(Name => "my_file.dat", Mode => In_Mode)'Access; begin No reason you can't write that package if you want. I would have the Open return a File_Access value, and would either have garbage collection semantics (via reference counts) for File_Type, or just not make it visible at all. But those are just details. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-22 0:00 ` Robert I. Eachus @ 1997-05-25 0:00 ` Matthew Heaney 1997-05-28 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-25 0:00 UTC (permalink / raw) In article <EACHUS.97May22142002@spectre.mitre.org>, eachus@spectre.mitre.org (Robert I. Eachus) wrote: > declare > The_File: New_IO.File_Access := > New_IO.Open(Name => "my_file.dat", Mode => In_Mode)'Access; > begin > > No reason you can't write that package if you want. I would have >the Open return a File_Access value, and would either have garbage >collection semantics (via reference counts) for File_Type, or just not >make it visible at all. But those are just details. Good idea, but I was trying to avoid using heap. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-25 0:00 ` Matthew Heaney @ 1997-05-28 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 120+ messages in thread From: Robert I. Eachus @ 1997-05-28 0:00 UTC (permalink / raw) I said: > declare > The_File: New_IO.File_Access := > New_IO.Open(Name => "my_file.dat", Mode => In_Mode)'Access; > begin > > No reason you can't write that package if you want. I would have >the Open return a File_Access value, and would either have garbage >collection semantics (via reference counts) for File_Type, or just not >make it visible at all. But those are just details. In article <mheaney-ya023680002505971159220001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > Good idea, but I was trying to avoid using heap. The thought that avoiding allocators in your code will avoid heap use when opening a file makes my head swim! Where does this insanity end? Does anyone know of a file system that allows "real" file objects to be deallocated or trashed by the user by accident? No? Okay, where do you think the real file buffers reside? On the user stack? On the system stack? How about in a system managed heap? On Unix, at least on Unix of a few years ago, I could have only twenty file descriptors open at a time. So use my suggestion above, disappear the File_Type from the user's view, and put everything into an array of twenty objects in the package body. What has this accomplished? Nothing. Much better would be to have an array of File_Access values and allocate objects from the heap when the file is opened, and deallocate them when the file is closed. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Robert I. Eachus @ 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney 1997-05-23 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Simon Wright 1 sibling, 2 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-23 0:00 UTC (permalink / raw) In article <mheaney-ya023680002105972302430001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > In article <JSA.97May21160340@alexandria>, jsa@alexandria (Jon S Anthony) wrote: > > > >That's more or less what Limited_Controlled gives you. You can "pass > >parameters" to Initialize via discriminants. You can also play the > >"rename the function result" game for limited types (which I think is > >actually pretty nice) and that does what you want as well. > > I think that using discriminants as "constructor arguments" is a real > kludge, and obfuscates declarations. Ada 95 doesn't have constructors, so > let's not try to fight the language. Who's fighting. That's what this stuff is there for. You can say it isn't done too well, but that's different. > Here is what I'd like to do: > > declare > The_File : File_Type'Open (Name => "my_file.dat", Mode => In_Mode); > begin > > Renaming a function return as a constant object won't fly, because I have > to modify the object. Well then, it's not of a limited type, now is it? which is the context that was being discussed... /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Jon S Anthony @ 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony 1997-05-28 0:00 ` Syntax for tagged record types (was Re David Kristola 1997-05-23 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Simon Wright 1 sibling, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-23 0:00 UTC (permalink / raw) In article <JSA.97May22203202@alexandria>, jsa@alexandria (Jon S Anthony) wrote: >> Here is what I'd like to do: >> >> declare >> The_File : File_Type'Open (Name => "my_file.dat", Mode => In_Mode); >> begin >> >> Renaming a function return as a constant object won't fly, because I have >> to modify the object. > >Well then, it's not of a limited type, now is it? which is the context >that was being discussed... I'm confused by your comment. My intentation was that the example refer to Text_IO.File_Type, which very definately is limited; perhaps that wasn't clear. What I am proposing is a new syntax, by adding a constructor abstraction; File_Type'Open in this example. (Today, in Ada 95, Text_IO.Open is an ordinary procedure.) It would look something like: constructor Open (Name : String; Mode : File_Mode) return File_Type; or maybe constructor File_Type'Open (Name : String; Mode : File_Mode); We want to "invoke" the constructor during the elaboration of the File_Type object. We can do so as in the example above, using the tic notation, or just allow the assignment operator ":=" for constructor invokations. We would allow this for limited types too, like the limited type in the example above. Allowing the assignment operator for limited types isn't as heretical as it may seem. We already allow it in renaming declarations, by saying that it's not really assignment. For example: package P is type T is limited private; type AT is range 1 .. 3; function Op (O : T) return AT; ... end P; procedure Proc (O : T) is function Op (O : T := 0) return AT renames P.Op; begin X := Op; In that renames of function Op, the assignment symbol is used for limited type T. So maybe we don't need the tic notation after all. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-25 0:00 ` Jon S Anthony 1997-05-28 0:00 ` Syntax for tagged record types (was Re David Kristola 1 sibling, 0 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-25 0:00 UTC (permalink / raw) In article <mheaney-ya023680002305971754170001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > What I am proposing is a new syntax, by adding a constructor abstraction; Oh. > File_Type'Open in this example. (Today, in Ada 95, Text_IO.Open is an > ordinary procedure.) It would look something like: > > constructor Open (Name : String; Mode : File_Mode) return File_Type; > > or maybe > > constructor File_Type'Open (Name : String; Mode : File_Mode); > > > We want to "invoke" the constructor during the elaboration of the File_Type Oh yeah. Bob Duff and I went 'round and 'round on this issue a few months back. Actually, maybe it was all the way back in the Fall. Specifically, it concerned why an allocator for a limited type was defined in terms of assignment when it was given an aggregate. Bob generalized the issue to say that, well, for limited types you should simply be able to initialize them other than by assignment and then this special case would be OK as well. Then someone posted a bit from the Annotated RM which got even more to the point that I was trying to say: for a limited type the _value_ is basically all there is (no variable really at all). Anyway, at that point, we all let the air out of our shoes and went home. /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony @ 1997-05-28 0:00 ` David Kristola 1 sibling, 0 replies; 120+ messages in thread From: David Kristola @ 1997-05-28 0:00 UTC (permalink / raw) In article ya023680002305971754170001@news.ni.net, mheaney@ni.net (Matthew Heaney) writes: >In article <JSA.97May22203202@alexandria>, jsa@alexandria (Jon S Anthony) wrote: > > >>> Here is what I'd like to do: >>> >>> declare >>> The_File : File_Type'Open (Name => "my_file.dat", Mode => In_Mode); >>> begin >>> >>> Renaming a function return as a constant object won't fly, because I have >>> to modify the object. [snip] >What I am proposing is a new syntax, by adding a constructor abstraction; >File_Type'Open in this example. (Today, in Ada 95, Text_IO.Open is an >ordinary procedure.) It would look something like: > > constructor Open (Name : String; Mode : File_Mode) return File_Type; > >or maybe > > constructor File_Type'Open (Name : String; Mode : File_Mode); [snip] Or how about a change to the rules that allow a constructor function (using normal function notation) when a limited object is created: declare -- Fine since this is creation The_File : File_Type := Text_IO.Open (Name => "my_file.dat", Mode => In_Mode); begin -- Illegal since The_File already exists. The_File := Text_IO.Open (Name => "my_other_file.dat", Mode => In_Mode); where in Text_IO, there is a function named Open that returns the limited type Text_IO.File_Type. The only time an object of a limited type could be set by a function is on creation. I would also be allowed to provide my own function, say one that checked a flag and returned Text_IO.Standard_Input or Text_IO.Open(...). Hmm, might this cause problems? Maybe mark the allowable functions with the word "limited" as in: limited function Open(...) return File_Type; Then, limited functions would only be allowed in the package that defines the limited type. If the implementation allowed The_File to contain whatever is returned by Standard_Input, then Standard_Input could also be marked as limited. I would hesitate to add a new key word to Ada, especially if existing key words could be used. But then, this is all just fancy. :-) --david kristola (not speaking for Lockheed Martin or SAMCO) (My news reader does not understand the firewall, oh well, automatic spam shield) Home: David95037 at aol dot com Work: davidk at os6 dot epc dot lmms dot lmco dot com Spam: eat-spam-and-die@dev.null ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-23 0:00 ` Simon Wright 1 sibling, 0 replies; 120+ messages in thread From: Simon Wright @ 1997-05-23 0:00 UTC (permalink / raw) jsa@alexandria (Jon S Anthony) writes: > > Renaming a function return as a constant object won't fly, because I have > > to modify the object. > > Well then, it's not of a limited type, now is it? which is the context > that was being discussed... It could be that he needs to pass it as an in out parameter .. -- Simon Wright Work Email: simon.j.wright@gecm.com GEC-Marconi Radar & Defence Systems Voice: +44(0)1705-701778 Command & Information Systems Divsion FAX: +44(0)1705-701800 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-20 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Jon S Anthony @ 1997-05-21 0:00 ` Mats Weber 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Samuel A. Mize 1 sibling, 2 replies; 120+ messages in thread From: Mats Weber @ 1997-05-21 0:00 UTC (permalink / raw) Matthew Heaney wrote: > I'm not dogmatic about the "pure" object-oriented syntax, ie > > declare > O : T; > begin > O.Op (A); > end; > > though I do think it's pretty hip. So do I. And if tasks and protected types provide that kind of notation, why should this not also be true for other constructs ? > What would be cool is to have a selector abstraction, to give you that for > free, ie > > type Stack is ...; > > selector Top (S : Stack) return Item; > > So that I could do this: > > declare > The_Stack : Stack; > begin > The_Item := The_Stack.Top; > ... That's why I proposed to use package types in my thesis (at <http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>). You example would be written package type Stack is function Top return Item; procedure Push (X : in Item); ... private ... end Stack; (just like a task or protected type). Of course there are a few restrictions on what you can put into a package type, for instance you can't declare a type within a package type. I chose the package type syntax because of similarities with task types, but there is absolutely no problem in changing the syntax to something different (for those allergic to package types :-), e.g. class type Stack is ... -- new keyword for OO types type Stack is record -- allow subprograms in records function Top return Item; procedure Push (X : in Item); ... end record; All three approaches are essentially equivalent. I chose package types because packages already have a private part, which is very useful, and because I make some further use of the task-package similarity that is very useful for expressing abstract data types that are needed in both concurrent and non-concurrent variants (e.g. Booch components). >[...] > It's always bothered me a bit (and Bertrand Meyer, too; read his book) that > the syntax for selecting an unencapsulated (public) component has to be > different from selecting an encapsulated one. > > The_Stack.Top vs. Top (The_Stack) > > Especially since we've sort of made this statement that tagged types are > "really" records, it would be cool to take the analogy a step farther, by > making component selection uniform. Absolutely. > While we're at it, maybe we can throw in real constructors, too. We can > solve the "problem" with limited types, by allowing a constructor to be > called in the declarative region. That way limited types wouldn't have to > be definate, or go on the heap unnecessarily. My proposal for constructors goes like this: package type T is procedure new (X : Integer; Y : Float); -- Note: new is a keyword ... end T; ... Object : T(X => 5, Y => 3.14); the elaboration of the object declaration creates the object and then calls the procedure new with the given parameters. This is very useful in many situations and does not have the limitations that are enforced on discriminants, and you can have several overloaded versions of the new procedure, wheareas discrimiants force you to have a fixed initialization formal part. Details of these proposed constructs can be found at the above URL. Class types provided this way (any of the above 3 syntax) do not specify the mode of the implicit parameter of the class type. This has the nice side effect that a function can modify the object on which it is applied, which would be very useful in cases like the random number generator discussed in another thread. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-21 0:00 ` Syntax for tagged record types and class types Mats Weber @ 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Mats Weber 1997-05-27 0:00 ` Tucker Taft 1997-05-22 0:00 ` Samuel A. Mize 1 sibling, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-21 0:00 UTC (permalink / raw) In article <33830D58.6D8F@elca-matrix.ch>, Mats.Weber@elca-matrix.ch wrote: >So do I. And if tasks and protected types provide that kind of notation, >why should this not also be true for other constructs ? Agreed. Selection should be consistent for all objects. The "principle of uniform reference," and all that. >That's why I proposed to use package types in my thesis (at ><http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>). >You example would be written > >package type Stack is That's a much more ambitious language change than I am suggesting. A package is a module, not a type, and it's simply the mechanism by which one controls namespace. Modules and types are orthogonal language constructs in Ada, and like it or not, we should keep it that way. >All three approaches are essentially equivalent. I chose package types >because packages already have a private part, which is very useful, and >because I make some further use of the task-package similarity that is >very useful for expressing abstract data types that are needed in both >concurrent and non-concurrent variants (e.g. Booch components). Adding selectors and constructors to the language is far simpler, and a much better fit to what is already there. The syntax for both can look like functions: type Stack is private; selector Top (S : Stack) return Item; or selector Stack.Top return Item; constructor Stack (Items : Item_Array); or constructor Initialize (Items : Item_Array) return Stack; So that I can do this: The_Stack : Stack'(1, 2, 3, 4, 5); or The_Stack : Stack'Initialize (1, 2, 3, 4, 5); I got the idea for a "named" constructor from Ian Joyner in has C++ Critique paper. We already have a precedent in the language for T'<function> in attributes, so we could borrow that for constructors. The tick comes from attribute syntax, plus from the fact that that is how you initialize a heap variable. It also gives us a way of avoiding the use of the assignment "operator," thus allowing a constructor "function" to initialize a limited object. That means limited objects don't have to be definate. Example, I could have a factory method to return an iterator that is limited and class-wide: procedure Copy (From : Root_Stack'Class; To : in out Root_Stack) is The_Iterator : Root_Stack_Iterator'Class'New_Iterator (From'Access); begin In Ada 95, I can only do the above example by putting the active iterator on the heap. >My proposal for constructors goes like this: > >package type T is > procedure new (X : Integer; Y : Float); -- Note: new is a keyword > ... >end T; > >... > >Object : T(X => 5, Y => 3.14); And my ideas were package P is type T is tagged private; constructor T (X : Integer; Y : Float); or constructor Initialize (X : Integer; Y : Float) return T; So that I could O : T (X => 5, Y => 3.14); O : T'(5, 3.14); -- do we need the tick? or O : T'Initialize (X => 5, Y => 3.14); Perhaps the need for a named constructor isn't obvious in this example. Consider this one: type File_Type is limited private; constructor Open (Name : String; Mode : File_Mode) return File_Type; declare The_File : File_Type'Open (Name => "mats_weber.dat", Mode => In_Mode); begin The_File is a modifiable object, just like it would be without the constructor. Perhaps we do need the tick; we wouldn't want to confuse discriminants with constructor arguments. At least the tick notation calls out the difference. Gee, isn't armchair language design fun? -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-21 0:00 ` Matthew Heaney @ 1997-05-22 0:00 ` Mats Weber 1997-05-27 0:00 ` Tucker Taft 1 sibling, 0 replies; 120+ messages in thread From: Mats Weber @ 1997-05-22 0:00 UTC (permalink / raw) To: Matthew Heaney Matthew Heaney wrote: > >package type Stack is > > That's a much more ambitious language change than I am suggesting. A I am not so sure. Package type is just an example of what the syntax could be (see my previous post). I have no problem calling them records. > package is a module, not a type, and it's simply the mechanism by which one > controls namespace. Modules and types are orthogonal language constructs > in Ada, and like it or not, we should keep it that way. OK. Make them records. I don't care, because I see package type Stack is procedure Push (X : in Item); function Top return Item; private ... end Stack; as equivalent to type Stack is record procedure Push (X : in Item); function Top return Item; private ... end record; If you don't like the idea of package types, think of them as records in which you can declare subprograms and that can have a private part. BTW, the syntax for task types could be type T is task entry E; end task; which would be more uniform with other type declarations in Ada. > >All three approaches are essentially equivalent. I chose package types > >because packages already have a private part, which is very useful, and > >because I make some further use of the task-package similarity that is > >very useful for expressing abstract data types that are needed in both > >concurrent and non-concurrent variants (e.g. Booch components). > > Adding selectors and constructors to the language is far simpler, and a > much better fit to what is already there. The syntax for both can look > like functions: Really ? You need two new keywords, I need zero :-) Seriously, I think constructors and selectors are easily modelled as procedures and functions, so I don't think it's worth adding new concepts here. > type Stack is private; > > selector Top (S : Stack) return Item; > or > selector Stack.Top return Item; > > constructor Stack (Items : Item_Array); > or > constructor Initialize (Items : Item_Array) return Stack; > > So that I can do this: > > The_Stack : Stack'(1, 2, 3, 4, 5); More probably The_Stack : Stack'((1, 2, 3, 4, 5)); (one set of parentheses for the qualified expression, and one for the array aggregate). > constructor Initialize (X : Integer; Y : Float) return T; > > So that I could > > O : T (X => 5, Y => 3.14); > O : T'(5, 3.14); -- do we need the tick? You do need the tick because otherwise it's the syntax for discriminants instead of constructor parameters (Ada is like that). ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Mats Weber @ 1997-05-27 0:00 ` Tucker Taft 1997-05-30 0:00 ` Mats.Weber 1 sibling, 1 reply; 120+ messages in thread From: Tucker Taft @ 1997-05-27 0:00 UTC (permalink / raw) Matthew Heaney (mheaney@ni.net) wrote: : In article <33830D58.6D8F@elca-matrix.ch>, Mats.Weber@elca-matrix.ch wrote: : >So do I. And if tasks and protected types provide that kind of notation, : >why should this not also be true for other constructs ? : Agreed. Selection should be consistent for all objects. The "principle of : uniform reference," and all that. Prefix notation, by which I mean <object>.<operation>, is reserved in Ada 95 for calls on "synchronizing" operations. The prefix object is the one controlling the synchronization. Hence, prefix notation is used for task entry calls, and protected operation calls only. In each of these cases, the prefix object is very special -- one must enter the synchronization domain of the prefix object before the operation is performed. Even if there are multiple parameters of the same task or protected type passed to the operation, the synchronization is associated only with the prefix object. For non-synchronizing operations, all parameters are treated symmetrically, and so the "principle of uniform reference" would argue that all such parameters belong inside the parentheses, rather than dangling out front. Furthermore, look at the nasty syntax in a language like C++ for talking about the "mode" of the implicit, prefix parameter. The word "const" is floating about in some unintuitive place in the function declaration. Finally, look at the nastiness associated with binary operators in C++ (and the complete lack of such binary operators in Eiffel and Java). In Ada 95, the "uniform reference" principle of treating all parameters uniformly eliminates all the kludgery associated with binary operations. Note that I am being a bit facetious here. There certainly are some advantages (and disadvantages) to using prefix notation. However, the notion that a single phrase like "uniform reference" can be used to justify one choice over another is a bit of a stretch in my view... : ... : Gee, isn't armchair language design fun? You bet. Of course, if you really want to have fun, try achieving international consensus on your design ... -- For what it is worth, my advice is to avoid using all the fancy syntactic features of your favorite OO language and stick with old function and procedure notation almost everywhere. Constructors, aggregates, and allocators should only be called inside "factory" routines. Operators should be reserved for numeric-ish types like complex numbers, vectors, and matrices. User-defined selectors, array indexers, etc., should be avoided; even using predefined selectors and array indexing should be confined to the implementation of query functions. Use procedures (aka void-returning functions) to change objects, and use functions to query objects. Use a "factory" function or procedure to create new objects. This approach will keep your abstraction "clean" and relatively language neutral, making it amenable to use with CORBA, (D)COM, etc., and other multi-lingual technologies (and people!). All of the "fruit salad" provided by some OO languages saves only a few keystrokes in most cases, and can significantly interfere with the ease with which others can pick up your code and understand it, reuse it, and enhance it. All the above IMVHO... : -------------------------------------------------------------------- : Matthew Heaney : Software Development Consultant : <mailto:matthew_heaney@acm.org> : (818) 985-1271 -- -Tucker Taft stt@inmet.com http://www.inmet.com/~stt/ Intermetrics, Inc. Burlington, MA USA ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-27 0:00 ` Tucker Taft @ 1997-05-30 0:00 ` Mats.Weber 0 siblings, 0 replies; 120+ messages in thread From: Mats.Weber @ 1997-05-30 0:00 UTC (permalink / raw) Tucker Taft wrote: > Prefix notation, by which I mean <object>.<operation>, is reserved in > Ada 95 for calls on "synchronizing" operations. The prefix object > is the one controlling the synchronization. Hence, prefix notation is > used for task entry calls, and protected operation calls only. ... and record components, and package components. I don't think that this convention helps us very much, because the language does not follow it in a consistent manner. For instance, when I see the expression Object.Nb_Items I don't know (without context) if it is a call to a protected function or the value of a record component. So I don't think that reserving the <object>.<operation> notation to synchronizing operations is really useful. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-21 0:00 ` Syntax for tagged record types and class types Mats Weber 1997-05-21 0:00 ` Matthew Heaney @ 1997-05-22 0:00 ` Samuel A. Mize 1997-05-22 0:00 ` Samuel A. Mize 1997-05-23 0:00 ` Mats Weber 1 sibling, 2 replies; 120+ messages in thread From: Samuel A. Mize @ 1997-05-22 0:00 UTC (permalink / raw) Mats Weber wrote: > > Matthew Heaney wrote: > > > I'm not dogmatic about the "pure" object-oriented syntax, ie > > > > declare > > O : T; > > begin > > O.Op (A); > > end; > > > > though I do think it's pretty hip. > > So do I. And if tasks and protected types provide that kind of notation, > why should this not also be true for other constructs ? > > > What would be cool is to have a selector abstraction, to give you that for > > free, ie > > > > type Stack is ...; > > > > selector Top (S : Stack) return Item; > > > > So that I could do this: > > > > declare > > The_Stack : Stack; > > begin > > The_Item := The_Stack.Top; > > ... > > That's why I proposed to use package types in my thesis (at > <http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>). I haven't read your thesis, so I can't address any other benefits of this proposal. However, you can get the prefix notation in Ada 95, by using a generic package. Of course, you don't want to duplicate all the procedures (especially if using a compiler like GNAT that does macro-expand-type generics!), so you would write your "package type" as a base package and an export-view generic package. This gives you the prefix notation. It's a bit more work. If you frequently want this notation, you should be able to write a preprocessor (I'd use a perl script) to generate the generic from the base package. I haven't compiled this example, but it shows the general idea: -------------------------------------------------------------- package Stack_Base is -- typical Ada abstract data type type Stack_Type is ... function Top (S: Stack_Type) return Item; procedure Push (S: Stack_Type; X : in Item); end Stack_Base; -------------------------------------------------------------- package body Stack_Base is -- left as an exercise for the reader -------------------------------------------------------------- generic package Stack is function Top return Item; Procedure Push (X: in Item); pragma Inline (Top, Push); end Stack; -------------------------------------------------------------- with Stack_Base; use Stack_Base; package body Stack is S: Stack_Type; function Top return Item is begin return Top (S); end Top; procedure Push (X: in Item) is begin Push (S, X); end Push; end Stack; Then you use Stack: declare package S is new Stack; I: Item; begin S.Push (I); if S.Top /= I then ... > > While we're at it, maybe we can throw in real constructors, too. We can > > solve the "problem" with limited types, by allowing a constructor to be > > called in the declarative region. That way limited types wouldn't have to > > be definate, or go on the heap unnecessarily. > > My proposal for constructors goes like this: > > package type T is > procedure new (X : Integer; Y : Float); -- Note: new is a keyword > ... > end T; > > ... > > Object : T(X => 5, Y => 3.14); In the Stack example above, we would have in Stack_Base: procedure Initialize (S: Stack_Type; X : Integer; Y : Float); and in the generic spec of Stack: generic X: Integer; Y: Float; package Stack is... and in the body of Stack, in the elaboration section: begin Initialize (S, X, Y); end Stack; As you say, > the elaboration of the object declaration creates the object and then > calls the procedure new with the given parameters. (replace "object declaration" with "package instantiation.") > Class types provided this way (any of the above 3 syntax) do not specify > the mode of the implicit parameter of the class type. This has the nice > side effect that a function can modify the object on which it is > applied, which would be very useful in cases like the random number > generator discussed in another thread. You can do this by using a procedure in the base package: procedure Top (S: in out Stack; I: out Item); and using that in a function call in the generic: function Top return Item is I: Item; begin Top (S, I); return I; end Top; Arguments against this approach: - it's more work - it doesn't provide other benefits of package types Arguments in favor of it: - it provides prefix syntax - you can do it today in Ada 95 Sam Mize -- -- Samuel Mize (817) 619-8622 "Team Ada" -- Hughes Training Inc. PO Box 6171 m/s 400, Arlington TX 76005 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-22 0:00 ` Samuel A. Mize @ 1997-05-22 0:00 ` Samuel A. Mize 1997-05-23 0:00 ` Mats Weber 1 sibling, 0 replies; 120+ messages in thread From: Samuel A. Mize @ 1997-05-22 0:00 UTC (permalink / raw) Samuel A. Mize wrote: >... However, you can get the prefix notation in Ada 95, by using a > generic package. [example deleted] > Arguments against this approach: > - it's more work > - it doesn't provide other benefits of package types It also doesn't allow you to have prefix notation for an object that is contained in an array or a record type. > Arguments in favor of it: > - it provides prefix syntax > - you can do it today in Ada 95 > > Sam Mize Sam Mize -- -- Samuel Mize (817) 619-8622 "Team Ada" -- Hughes Training Inc. PO Box 6171 m/s 400, Arlington TX 76005 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types and class types 1997-05-22 0:00 ` Samuel A. Mize 1997-05-22 0:00 ` Samuel A. Mize @ 1997-05-23 0:00 ` Mats Weber 1 sibling, 0 replies; 120+ messages in thread From: Mats Weber @ 1997-05-23 0:00 UTC (permalink / raw) Samuel A. Mize wrote: > I haven't read your thesis, so I can't address any other benefits of this > proposal. However, you can get the prefix notation in Ada 95, by using a > generic package. To make things clear, the main reason why I proposed package types (or subprograms in records) is not for the prefix notation, but for providing object oriented constructs (inheritance, polymorphism, ...). The prefix notation just came naturally with the constructs I proposed, but I am not fanatic about it at all. But I still think that it makes a few things simpler, and more natural to most people, than tagged types. For instance it is very clear that the prefix is used for selecting the subprogram to be called in a dispatching call, whereas tagged types need complicated rules for defining the controlling operand(s) (see for instance RM 3.9.3(16)). There is a more complete comparison of tagged types vs package types in my thesis. > [...] example of class implemented as a generic deleted. Of course you can do it this way, but it's just not workable. Generic instances are not objects and all you can do is declare them in a certain scope, you can't copy them around, you can't declare an array of them, you can't allocate them dynamically, etc. ^ permalink raw reply [flat|nested] 120+ messages in thread
[parent not found: <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net>]
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) [not found] ` <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net> @ 1997-05-22 0:00 ` Robert A Duff 1997-05-22 0:00 ` John G. Volan 0 siblings, 1 reply; 120+ messages in thread From: Robert A Duff @ 1997-05-22 0:00 UTC (permalink / raw) In article <mheaney-ya023680002105972302430001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >I think that using discriminants as "constructor arguments" is a real >kludge, and obfuscates declarations. ... Why? - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-22 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Robert A Duff @ 1997-05-22 0:00 ` John G. Volan 1997-05-23 0:00 ` Matthew Heaney 1997-05-23 0:00 ` Jon S Anthony 0 siblings, 2 replies; 120+ messages in thread From: John G. Volan @ 1997-05-22 0:00 UTC (permalink / raw) Robert A Duff wrote: > > In article <mheaney-ya023680002105972302430001@news.ni.net>, > Matthew Heaney <mheaney@ni.net> wrote: > >I think that using discriminants as "constructor arguments" is a real > >kludge, and obfuscates declarations. ... > > Why? > > - Bob If the hypothetical constructor only took discrete or access-type parameters, then faking those "parameters" as discriminants on a limited type is okay. But if they have to be any other kind of type, you've got a problem. Faking a parameter of type "T" as a discriminant of type "access T" only leaves the programmer with a dilemma: Who is responsible for deallocating the designated T object? The answers might be: (1) The object with the discriminant. (It "owns" the designated T object, so it should deallocate it on Finalize). (2) The client who passed the T into the discriminant. (It may have passed the same T access value as a discriminant to several objects, so it should deallocate the designated T object only once all those other objects are finalized). (3) Nobody. The T object was never allocated on the heap in the first place. It was aliased, and 'Access was passed to the discriminant. This doesn't make for very clean abstractions. Choice (1) might be the most attractive from an abstraction point a view, but it requires that clients be highly circumspect in their behavior towards those access discriminants (they must always do a "new" but never a 'Access, and they must never do Unchecked_Deallocation) but this restriction is not enforceable by the compiler. Another issue with discriminants as constructor parameters is that there is no provision for having multiple overloaded constructors with different sets of parameters. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-22 0:00 ` John G. Volan @ 1997-05-23 0:00 ` Matthew Heaney 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Jon S Anthony 1 sibling, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-23 0:00 UTC (permalink / raw) In article <33850721.49BF@sprintmail.com>, johnvolan@sprintmail.com wrote: >Another issue with discriminants as constructor parameters is that there >is no provision for having multiple overloaded constructors with >different sets of parameters. Which is precisely the reason for having named constructors. The parameters alone don't tell you enough information. Not being able to give the different constructors for a type a descriptive name was cited as a criticism of C++ in Joyner's paper. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney 1997-05-23 0:00 ` John G. Volan 0 siblings, 2 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-23 0:00 UTC (permalink / raw) In article <mheaney-ya023680002305970103110001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > >Another issue with discriminants as constructor parameters is that there > >is no provision for having multiple overloaded constructors with > >different sets of parameters. > > Which is precisely the reason for having named constructors. The > parameters alone don't tell you enough information. Not being able to give > the different constructors for a type a descriptive name was cited as a > criticism of C++ in Joyner's paper. This is a non issue for anything other than a limited type. You can name your constructors whatever you want, they can take any number of parameters and there can be any number of them. For limited types, the only way around this is to hide them behind access types for them. Then things again work just fine - except for storage management issues. Hence, the need for GC. Limited types are really extremely useful. Unfortunately, much of this is lost without GC support. /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Jon S Anthony @ 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony ` (2 more replies) 1997-05-23 0:00 ` John G. Volan 1 sibling, 3 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-23 0:00 UTC (permalink / raw) In article <JSA.97May23142418@alexandria>, jsa@alexandria (Jon S Anthony) wrote: >For limited types, the only way around this is to hide them behind >access types for them. Then things again work just fine - except for >storage management issues. Hence, the need for GC. Limited types are >really extremely useful. Unfortunately, much of this is lost without >GC support. But I'm trying to avoid using any heap. If I have to allocate an object, I'd rather it go on the stack. Limitedness forces me to put the object on the heap. Why? It's just a syntactic quirk of the language (the confusion of assignment and initialization) that prevents me from initializing a limited object during its elaboration. If we could eliminate those times when a limited object must be put on the heap, then there would be less motivation for a garbage collector. Safety-critical applications won't use the heap, so let's try to build a more expressive language for use on those kinds of applications. Eliminate the requirement for heap - by adding features (such as constructors) for applicative programming using limited types - and you eliminate the need for a garbage collector. It's not clear to me, though, why you even need GC support. If heap is needed to implement an abstraction, the abstraction writer can sweat all the memory management details by using storage pools and controlled types. What's the problem? -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-25 0:00 ` Jon S Anthony 1997-05-25 0:00 ` Robert Dewar 1997-05-27 0:00 ` Ray Blaak 2 siblings, 0 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-25 0:00 UTC (permalink / raw) In article <mheaney-ya023680002305972133010001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > >For limited types, the only way around this is to hide them behind > >access types for them. Then things again work just fine - except for > >storage management issues. Hence, the need for GC. Limited types are > >really extremely useful. Unfortunately, much of this is lost without > >GC support. > > But I'm trying to avoid using any heap. If I have to allocate an object, > I'd rather it go on the stack. Limitedness forces me to put the object on > the heap. Why? Who said it forces you to put them on the heap? It's your wanting to have all sorts of "constructors" for them with all sorts of parameters and named all sorts of ways and such that basically makes this necessary. > It's just a syntactic quirk of the language (the confusion > of assignment and initialization) that prevents me from initializing a So, why are you using limited types anyway? > If we could eliminate those times when a limited object must be put > on the heap, then there would be less motivation for a garbage > collector. Talk about having the cart before the horse! > It's not clear to me, though, why you even need GC support. If heap is > needed to implement an abstraction, the abstraction writer can sweat all > the memory management details by using storage pools and controlled types. > What's the problem? Go ask a typical C or C++ programmer for starters. Highly threaded and interconnected structures are extremely common and are often the best (most natural, most efficient, most flexible, etc) implmentations of many abstractions. Such structures basically _require_ heap style allocation and reference interconnection. Sure, it is _possible_ to manage this sort of complexity by hand, but it is extremely time consuming grunt type work - the very thing that computers are good at! That's the problem and that's the reason why GC is so useful. Why use the stack? Just allocate everything statically like old Fortran. Hey, you can make this work for anything - who needs all that assistance you get with stack allocation? /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony @ 1997-05-25 0:00 ` Robert Dewar 1997-05-27 0:00 ` Ray Blaak 2 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-25 0:00 UTC (permalink / raw) Matthew says <<Safety-critical applications won't use the heap, so let's try to build a more expressive language for use on those kinds of applications. Eliminate the requirement for heap - by adding features (such as constructors) for applicative programming using limited types - and you eliminate the need for a garbage collector.>> That's an over-generalization. Many safety critical programming protocols allow the use of the heap for allocation only at initialization time. Otherwise you end up with quite unnecessary restrictions that do not add to safety, e.g. you lose the possibility of parametrizing sizes of variable length objects. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony 1997-05-25 0:00 ` Robert Dewar @ 1997-05-27 0:00 ` Ray Blaak 2 siblings, 0 replies; 120+ messages in thread From: Ray Blaak @ 1997-05-27 0:00 UTC (permalink / raw) mheaney@ni.net (Matthew Heaney) writes: >But I'm trying to avoid using any heap. If I have to allocate an object, >I'd rather it go on the stack. Limitedness forces me to put the object on >the heap. Why? It's just a syntactic quirk of the language (the confusion >of assignment and initialization) that prevents me from initializing a >limited object during its elaboration. If we could eliminate those times >when a limited object must be put on the heap, then there would be less >motivation for a garbage collector. This might be tedious, but you can get limited types on the stack via function parameters: declare procedure Doit (To_Me : in out Some_Limited_Type) is begin blah blah end Doit; begin Doit(To_Me => My_Constructor ("foobar")); end; Cheers, Ray Blaak blaak@mda.ca ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-23 0:00 ` John G. Volan 1997-05-24 0:00 ` Robert A Duff 1997-05-25 0:00 ` Jon S Anthony 1 sibling, 2 replies; 120+ messages in thread From: John G. Volan @ 1997-05-23 0:00 UTC (permalink / raw) I (John Volan) wrote: >Another issue with discriminants as constructor parameters is that there >is no provision for having multiple overloaded constructors with >different sets of parameters. Jon S Anthony replied: > > This is a non issue for anything other than a limited type. You can > name your constructors whatever you want, they can take any number of > parameters and there can be any number of them. My reply: Just so folks won't be confused, what Jon's referring to here are ordinary Ada functions that happen to return a value of a given type, e.g. type Some_Value_Type is ... -- something non-limited function Make_Some_Value (... from one set of parameters ...) return Some_Value_Type; function Make_Some_Value (... from another set of parameters ...) return Some_Value_Type; ... etc. This then allows a user to construct a value of the given type during an object declaration, in the initialization part: Some_Value : Some_Value_Type := Make_Some_Value (...); The designer of the abstraction can even force users to always call one of these constructor functions, by giving the type an unknown discriminant part, thereby making it an "indefinite" type: type Some_Value_Type (<>) is ... private; -- something non-limited This doesn't mean the actual completion of this type has to have a discriminant, but it does make uninitialized variables illegal: Some_Value : Some_Value_Type; -- compiler error! indefinite type! This restriction is appropriate if the abstraction just doesn't include any notion of a "default" constructor. > For limited types, the only way around this is to hide them behind > access types for them. Right, when you deal with true object-oriented abstractions (as opposed to value-oriented abstract data types), you inevitably have to invoke reference semantics and the identity-vs-state issue. Here's a pattern I like to use for object-oriented types: type Some_Object_Type (<>) is tagged limited private; type Some_Object_Access_Type is access all Some_Object_Type'Class; function Make_Some_Object (... from one set of parameters ...) return Some_Object_Access_Type; function Make_Some_Object (... from another set of parameters ...) return Some_Object_Access_Type; ... procedure Primitive_Operation (Some_Object : access Some_Object_Type; ... parameters ... ); ... etc. Note that: (1) Some_Object_Type is limited, so assignment can't be used to casually copy the state of one object into another. (Althought the abstraction designer could certainly choose to provide subprograms that do deep copies, but calling these subprograms wouldn't be "casual".) (2) On the other hand, Some_Object_Access_Type is (of course) _not_ limited, so assignments can be used to copy object _identities_ (access values, "references" to objects) as much as you please. (3) Some_Object_Type has an unknown discriminant part, so a direct declaration for an object of this type is illegal: Some_Object : Some_Object_Type; -- compiler error! indefinite type! And the users can't get around this by trying to initialize the object to something -- because it's a limited type, so assignment is illegal. Instead, the users are forced to go through one of the constructors defined for the abstraction: Some_Object : Some_Object_Access_Type := Make_Some_Object (...); But note that what we have here is only an _access_ to some object. The abstraction has complete control over where that object actually is. (The object will commonly be allocated on the heap, but that's not necessarily the only possibility.) (4) Since the constructor functions all return values of the access type and not the object type itself, these functions are _not_ primitive subprograms for the object type, so they will _not_ be inherited by derived types ("subclasses"). This is actually a good thing: It has frequently been argued that constructors should not be inheritable. (In fact, C++'s constructors aren't.) (5) If a subclass can't just inherit a constructor, and the parent class doesn't include a default constructor, then the only way the subclass can properly implement a constructor of its own is if it somehow has access to the implementation details of its parent class. That pretty much forces you to put your subclasses into child packages. Giving the base type an unknown discriminant also forces this, because it's illegal to derive a new type unless you can provide a constraint for the discriminant (or "see" that there really isn't one). To make it a little easier to implement child constructors, I like to use a pattern where, for every visible constructor _function_ which I provide to clients, I accompany it with a private constructor _procedure_, which the constructor function calls, and which child constructors can also call: package Base_Class is type Base_Type (<>) is tagged limited private; type Base_Access_Type is access all Base_Type'Class; function Make_Base (...some base set of parameters...) return Base_Access_Type; ... private type Base_Type is tagged limited record ... procedure Make_Base (Base : access Base_Type'Class; ...same base set of parameters...); ... end Base_Class; A Make_... function would typically allocate a new object from somewhere, then call the corresponding hidden Make_... procedure to initialize the object, then return the new access value. Note that I write my Make_... procedures as _classwide_ subprograms, so they aren't inheritable primitives any more than my Make_... functions. A subclass package would look something like this: package Base_Class.Derived_Class is type Derived_Type (<>) is new Base_Type with private; type Derived_Access_Type is access all Derived_Type'Class; function Make_Derived (...base parameters...plus others maybe...) return Derived_Access_Type; ... private type Derived_Type is new Base_Type with record ... procedure Make_Derived (Derived : access Derived_Type'Class; ...base parameters...plus others maybe...); ... end Base_Class.Derived_Class; The derived Make_... procedure for a subclass like this would typically call the base Make_... procedure for its parent class, and then would do whatever additionally initializations are needed for its type extension. Since the derived class is in a child package, it can "see" the hidden base Make_... procedure. And since the base-type object initialized by the base Make_... procedure is a classwide parameter, the derived Make_... procedure can pass its derived-type object into this parameter. > Then things again work just fine - except for > storage management issues. Hence, the need for GC. Limited types are > really extremely useful. Unfortunately, much of this is lost without > GC support. Agreed. ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` John G. Volan @ 1997-05-24 0:00 ` Robert A Duff 1997-05-24 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony 1 sibling, 1 reply; 120+ messages in thread From: Robert A Duff @ 1997-05-24 0:00 UTC (permalink / raw) In article <33867D87.21BA@sprintmail.com>, John G. Volan <johnvolan@sprintmail.com> wrote: >This then allows a user to construct a value of the given type during an >object declaration, in the initialization part: > > Some_Value : Some_Value_Type := Make_Some_Value (...); This sort of thing could make sense for limited types, too -- as others have pointed out, Ada *confuses* initialization and assignment. However, it seems tricky to implement: type T is limited record A_Task: Some_Task_Type; ... -- etc. end record; function F return T is ... begin ... declare Result: T; begin return Result; end; ... end F; function G return T is begin ... return F; ... end G; X: T := G; -- Not Ada. If the above were legal, the compiler would need to allocate the deeply-nested Result object in a non-nested place (on the heap?), since it would "become" the object X. No fair copying Result into X, since the type is limited. The seems a bit tricky, especially in the case where the functions return something whose size is unknown at the point of the call. >The designer of the abstraction can even force users to always call one >of these constructor functions, by giving the type an unknown >discriminant part, thereby making it an "indefinite" type: > > type Some_Value_Type (<>) is ... private; -- something non-limited > >This doesn't mean the actual completion of this type has to have a >discriminant, but it does make uninitialized variables illegal: > > Some_Value : Some_Value_Type; -- compiler error! indefinite type! > >This restriction is appropriate if the abstraction just doesn't include >any notion of a "default" constructor. Yes, I think this is a nice capability. >(4) Since the constructor functions all return values of the access type >and not the object type itself, these functions are _not_ primitive >subprograms for the object type, so they will _not_ be inherited by >derived types ("subclasses"). This is actually a good thing: It has >frequently been argued that constructors should not be inheritable. (In >fact, C++'s constructors aren't.) In Ada, constructors (i.e. functions that are primitive-on-result) are inherited, but become abstract, so you have to override them explicitly (unless the derived type is abstract). If you don't want to override them, then return the class-wide type (or, as above, a pointer). >(5) If a subclass can't just inherit a constructor, and the parent class >doesn't include a default constructor, then the only way the subclass >can properly implement a constructor of its own is if it somehow has >access to the implementation details of its parent class. That pretty >much forces you to put your subclasses into child packages. Giving the >base type an unknown discriminant also forces this, because it's illegal >to derive a new type unless you can provide a constraint for the >discriminant (or "see" that there really isn't one). Umm, I don't think there is any such rule. See 3.7(26). - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-24 0:00 ` Robert A Duff @ 1997-05-24 0:00 ` Matthew Heaney 1997-05-28 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-24 0:00 UTC (permalink / raw) In article <EApCsn.Fsy@world.std.com>, bobduff@world.std.com (Robert A Duff) wrote: >This sort of thing could make sense for limited types, too -- as others >have pointed out, Ada *confuses* initialization and assignment. >However, it seems tricky to implement: > > type T is limited > record [snip] > > function G return T is > begin > ... > return F; > ... > end G; > > X: T := G; -- Not Ada. > >If the above were legal, the compiler would need to allocate the >deeply-nested Result object in a non-nested place (on the heap?), since >it would "become" the object X. No fair copying Result into X, since >the type is limited. The seems a bit tricky, especially in the case >where the functions return something whose size is unknown at the point >of the call. Which is part of the reason I'm advocating a different abstraction - a constructor abstraction rather than a function (which is an expression abstraction). With a constructor abstraction, we are free to impose whatever restrictions are necessary to make construction work. The statement X : T := G; would remain illegal, assuming G is a function. If the representation of T contains a limited component, then perhaps the rule could be that T has to be definate (so we can avoid an illegal copy?). Maybe not: we just need some way of allocating the object on the stack, and letting the constructor manipulate that object, so that no copying is ever required. It would be really swell too, if in the constructor we were able to invoke the constructors for the object's components. An important goal, though, is for constructors for limited types that are indefinate. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-24 0:00 ` Matthew Heaney @ 1997-05-28 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 120+ messages in thread From: Robert I. Eachus @ 1997-05-28 0:00 UTC (permalink / raw) In article <mheaney-ya023680002405971626500001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > Maybe not: we just need some way of allocating the object on the > stack, and letting the constructor manipulate that object, so that > no copying is ever required. It would be really swell too, if in > the constructor we were able to invoke the constructors for the > object's components. > An important goal, though, is for constructors for limited types > that are indefinate. Hmmm. Let's imagine a generic package: generic type Object_Type(<>) is limited private; type Object_Ref is access Object_Type; ... package Constructor is Object: Object_Ref; end Constructor; pragma Elaborate_Body(Constructor); package body Constructor is ... end Constructor; Now every time I instantiate this package, I create an Object_Ref, and in the body I initialize it to point to a value in the body. For some types the body can be completely in Ada, for others you might have to use extensions/magic tricks/Unchecked_Conversions, etc. in the body, and in particular, the decision whether or not to call Unchecked_Access will almost certainly a significant design issue. When I have played this game, I've done it three different ways: 1) N objects in the package which declares the type, and the generic packages do reference counting. (Actually, it is easier to make the _ref type a controlled type to begin with, but I digress.) 2) Unchecked_Access and programming standards about copying the pointer object. (Or you could try making that type limited, but leave out the unknown discriminants.) 3) Garbage collection provided courtesy of Unbounded_String. Be careful to understand the game here. The safest is to have a (private) token type which is access Unbounded_String, and a conversion which produces an Object_Ref from it. To do otherwise, you have to look at the implementation of Unbounded_String. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-23 0:00 ` John G. Volan 1997-05-24 0:00 ` Robert A Duff @ 1997-05-25 0:00 ` Jon S Anthony 1 sibling, 0 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-25 0:00 UTC (permalink / raw) In article <33867D87.21BA@sprintmail.com> "John G. Volan" <johnvolan@sprintmail.com> writes: > Just so folks won't be confused, what Jon's referring to here are > ordinary Ada functions that happen to return a value of a given type, Right. > > For limited types, the only way around this is to hide them behind > > access types for them. > > Right, when you deal with true object-oriented abstractions (as opposed > to value-oriented abstract data types), you inevitably have to invoke > reference semantics and the identity-vs-state issue. > > Here's a pattern I like to use for object-oriented types: > > type Some_Object_Type (<>) is tagged limited private; > type Some_Object_Access_Type is access all Some_Object_Type'Class; > > function Make_Some_Object (... from one set of parameters ...) > return Some_Object_Access_Type; <...> Exactly! Right on the mark. > (1) Some_Object_Type is limited, so assignment can't be used to casually Absolutely. > (3) Some_Object_Type has an unknown discriminant part, so a direct > declaration for an object of this type is illegal: > > Some_Object : Some_Object_Type; -- compiler error! indefinite type! Absolutely! > And the users can't get around this by trying to initialize the object > to something -- because it's a limited type, so assignment is illegal. Exactly! > > Then things again work just fine - except for > > storage management issues. Hence, the need for GC. Limited types are > > really extremely useful. Unfortunately, much of this is lost without > > GC support. > > Agreed. Well, with some luck this will not be so much an issue by some time this summer! :-) If I could only get out from under this proposal writing rubbish... /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Syntax for tagged record types (was Re: Not intended for use in medical,) 1997-05-22 0:00 ` John G. Volan 1997-05-23 0:00 ` Matthew Heaney @ 1997-05-23 0:00 ` Jon S Anthony 1 sibling, 0 replies; 120+ messages in thread From: Jon S Anthony @ 1997-05-23 0:00 UTC (permalink / raw) In article <33850721.49BF@sprintmail.com> "John G. Volan" <johnvolan@sprintmail.com> writes: > for deallocating the designated T object? The answers might be: > > (1) The object with the discriminant. (It "owns" the designated T > object, so it should deallocate it on Finalize). > > (2) The client who passed the T into the discriminant. (It may have > passed the same T access value as a discriminant to several objects, so > it should deallocate the designated T object only once all those other > objects are finalized). > > (3) Nobody. The T object was never allocated on the heap in the first > place. It was aliased, and 'Access was passed to the discriminant. (4) The GC... > This doesn't make for very clean abstractions. Choice (1) might be the (4) eliminates this issue completely... /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar ` (2 preceding siblings ...) 1997-05-12 0:00 ` John G. Volan @ 1997-05-12 0:00 ` John G. Volan 3 siblings, 0 replies; 120+ messages in thread From: John G. Volan @ 1997-05-12 0:00 UTC (permalink / raw) Robert Dewar wrote: > > John said > > <<So why do we have inheritance in Ada95? Because, quite simply, it was > perceived by many that Ada9X would be doomed to utter extinction if it > did not become a fully object-oriented language.>> > > This is just wrong, you like to guess about things, but you were not > there, and so it is not surprising that your guesses bear little > relationship to reality. > > One of the things that is becoming generally agreed in programming > languages is that you need both genericity (for parametrized abstractions) > and inheritance (for extensible abstractions. Ada 83 had one and not the > other, This is not precisely correct: Ada83 _did_ have inheritance, which has been often overlooked. Derived types have always inherited their structure, and all their primitive operations (as they are now called), from their parent types. What is new in Ada95 is type _extension_, which tagged types provide, along with classwide programming and dynamic dispatching. I make this point because it is to the credit of the Ada9X team that they were able to achieve the goal of making Ada95 fully OO by taking what was already inherent in Ada83 and extending it in a very natural way, rather than encrusting the language with an entirely new construct (e.g. class types or package types). ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Language Design Mistakes (was "not intended...") 1997-05-10 0:00 ` Robert Dewar 1997-05-10 0:00 ` John G. Volan @ 1997-05-12 0:00 ` W. Wesley Groleau (Wes) 1997-05-13 0:00 ` Robert Dewar 1 sibling, 1 reply; 120+ messages in thread From: W. Wesley Groleau (Wes) @ 1997-05-12 0:00 UTC (permalink / raw) Robert Dewar wrote: > Similarly, Fortran users will never put up with having to declare > all those array types, so let's allow anonymous array declarations: > > My opinion is that both these decisions are mistakes, they introduce > irregularity and confusion. As Robert said, making a design decision to placate a Fortran user is a mistake. But there is a place for arrays of anonymous types. If there is no conceivable reason for ever passing the value of an array to a subprogram or entry, or assigning to or from the array or a slice of it, then it will always be the only array of its type, so a superfluous type declaration is merely clutter _hindering_ source readability. (Some say the type name can be chosen for documentation value, but I don't see why that can't all go into the object name.) Since arrays that do not meet the above "uniqueness test" are quite awkward to handle anonymously (due to "strong typing"), there is no need for rigid "thou shalt never use an anonymous array type" rules. I have viewed a lot of code in my career, and I'm not just speculating when I call a superfluous type declaration "detracting clutter." (BTW, if an array type has only one instance, but additional variable/ parameter instances are "conceivable," then I do not take the above viewpoint.) * The rest of Robert's post I agreed with. ---------------------------------------------------------------------- Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA Senior Software Engineer - AFATDS Tool-smith Wanna-be w w g r o l at p s e u l t 0 1 dot f w dot h a c dot c o m SPAM should be sent to I.want.one@mailbombs.for.idiots.org If you don't want to pay $500 (see 47 USC 227), don't send it here. ---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Language Design Mistakes (was "not intended...") 1997-05-12 0:00 ` Language Design Mistakes (was "not intended...") W. Wesley Groleau (Wes) @ 1997-05-13 0:00 ` Robert Dewar 1997-05-13 0:00 ` W. Wesley Groleau (Wes) 1997-05-13 0:00 ` Robert A Duff 0 siblings, 2 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-13 0:00 UTC (permalink / raw) Wes said <<If there is no conceivable reason for ever passing the value of an array to a subprogram or entry, or assigning to or from the array or a slice of it, then it will always be the only array of its type, so a superfluous type declaration is merely clutter _hindering_ source readability. (Some say the type name can be chosen for documentation value, but I don't see why that can't all go into the object name.)>> OK, but just make sure you know the rules. If you think this way, it is all too easy to expect this to extend to a protected object that protects an array, this is a very common syntactic error. Or that it extends to a single field of a record that appears only once. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Language Design Mistakes (was "not intended...") 1997-05-13 0:00 ` Robert Dewar @ 1997-05-13 0:00 ` W. Wesley Groleau (Wes) 1997-05-13 0:00 ` Robert A Duff 1 sibling, 0 replies; 120+ messages in thread From: W. Wesley Groleau (Wes) @ 1997-05-13 0:00 UTC (permalink / raw) Robert Dewar wrote: > > Wes said > > <<If there is no conceivable reason for ever passing the value of an > array to a subprogram or entry, or assigning to or from the array > or a slice of it, then it will always be the only array of its type, > so a superfluous type declaration is merely clutter _hindering_ > source readability. (Some say the type name can be chosen for > documentation value, but I don't see why that can't all go into > the object name.)>> > > OK, but just make sure you know the rules. If you think this way, it is > all too easy to expect this to extend to a protected object that protects > an array, this is a very common syntactic error. Or that it extends to > a single field of a record that appears only once. I am aware of those rules, but even if I was not, the compiler would enforce them. Hence, there is still no need for a coding standard that people can use to "substitute for judgment." ---------------------------------------------------------------------- Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA Senior Software Engineer - AFATDS Tool-smith Wanna-be w w g r o l at p s e u l t 0 1 dot f w dot h a c dot c o m SPAM should be sent to I.want.one@mailbombs.for.idiots.org If you don't want to pay $500 (see 47 USC 227), don't send it here. ---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Language Design Mistakes (was "not intended...") 1997-05-13 0:00 ` Robert Dewar 1997-05-13 0:00 ` W. Wesley Groleau (Wes) @ 1997-05-13 0:00 ` Robert A Duff 1997-05-14 0:00 ` Robert Dewar 1 sibling, 1 reply; 120+ messages in thread From: Robert A Duff @ 1997-05-13 0:00 UTC (permalink / raw) In article <dewar.863496826@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Wes said > ><<If there is no conceivable reason for ever passing the value of an >array to a subprogram or entry, or assigning to or from the array >or a slice of it, then it will always be the only array of its type, >so a superfluous type declaration is merely clutter _hindering_ >source readability. (Some say the type name can be chosen for >documentation value, but I don't see why that can't all go into >the object name.)>> This is true, but if the language is going to allow this for arrays and tasks, it should allow it for all types. That would make the language simpler, by making it more uniform. It might even be useful, once in a while: Recursion_Count: range 0..100 := 0; -- "range 0..100" declares an -- anonymous integer type. -- This isn't Ada. function F(...) return ... is begin Recursion_Count := Recursion_Count + 1; -- Blow up if runaway recursion ... F(...) ... Recursion_Count := Recursion_Count - 1; end F; This is better than having a named type, for the reasons stated by Wes, above. And it's better than using an existing type, such as Integer, because it clearly expresses the fact that Recursion_Count isn't being freely mixed with any other integer variables, which is a useful fact when understanding the program. Note that protected types (originally called protected *records*) can be anonymous, making them uniform with tasks, but not with records. >OK, but just make sure you know the rules. If you think this way, it is >all too easy to expect this to extend to a protected object that protects >an array, this is a very common syntactic error. Or that it extends to >a single field of a record that appears only once. There was some push for Ada 9X to allow anonymous arrays for record components and the like, for uniformity, but it adds complexity, and so we decided it wasn't worth it. Where does that anon array type get implicitly declared? Certainly not just before the component_decl (which would be analogous to the object_decl case), because that would result in nested types, which cause semantic trouble. Certainly not just before the record type decl, because then you couldn't make the bounds depend on discriminants, which would be an unexpected non-uniformity. Maybe the array type gets implicitly declared before the record, and its first subtype before the component? - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Language Design Mistakes (was "not intended...") 1997-05-13 0:00 ` Robert A Duff @ 1997-05-14 0:00 ` Robert Dewar 0 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Bob Duff said <<This is true, but if the language is going to allow this for arrays and tasks, it should allow it for all types. That would make the language simpler, by making it more uniform. It might even be useful, once in a while:>> My example here would be System_Status : (Going, Stopped, Terminating); but allowing anonymous types uniformly, as Bob Duff said, would lead to a huge increase in complexity for relatively little gain (Even thinking about implementing it in GNAT makes my head ache :-) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-07 0:00 ` Robert Dewar 1997-05-08 0:00 ` John G. Volan @ 1997-05-08 0:00 ` Robert A Duff 1997-05-09 0:00 ` Robert I. Eachus 1997-05-08 0:00 ` Kaz Kylheku 2 siblings, 1 reply; 120+ messages in thread From: Robert A Duff @ 1997-05-08 0:00 UTC (permalink / raw) In article <dewar.863062734@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >There is something potentially wrong, which is that compact operation >notations like this are most happy with short identifier names, as in > > a++; > >not nearly so pretty is > > Average_Daily_Rate_Of_Pay++; Well, I suppose, but you could make the same argument about various notations that *are* in Ada. E.g.: Average_Daily_Rate_Of_Pay:=Some_Other_Big_Fat_Identifier_Name; If I write it without spaces, the ":=" tends to get lost (compared to "x:=y;"). If Ada had "++", I would probably write: Average_Daily_Rate_Of_Pay ++ ; which doesn't look so bad to me. Nor does: Average_Daily_Rate_Of_Pay += 1; which is certainly no worse in this regard than: Average_Daily_Rate_Of_Pay := 1; Instead of ++, I would be just as happy with: Increment(Average_Daily_Rate_Of_Pay); But my point was that the side-effect issue is more important than this lexical stuff. I would object to: Nice_Long_Array_Name[Increment(Nice_Long_Integer_Name)] := ...; on the same basis (where this (evil) Increment both modifies its argument, and returns a result). I realize I'm mixing Ada and C notation there. >Well of course this is not the only reason that C programmers so often >favor short cryptic identifier names (and of course there is nothing in C >which requires them), but it is a contributing factor! Perhaps. Who knows? I think it's mainly a cultural thing -- everybody does it that way, so new programmers learn to do it that way. - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` Not intended for use in medical, Robert A Duff @ 1997-05-09 0:00 ` Robert I. Eachus 1997-05-11 0:00 ` Robert Dewar 0 siblings, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-09 0:00 UTC (permalink / raw) In article <E9vH6G.88E@world.std.com> bobduff@world.std.com (Robert A Duff) writes: > Instead of ++, I would be just as happy with: > Increment(Average_Daily_Rate_Of_Pay); So use it. This is perfectly legal Ada, and I have a package kicking around somewhere with those "additional" operations which are procedures. > But my point was that the side-effect issue is more important than this > lexical stuff. I would object to: > Nice_Long_Array_Name[Increment(Nice_Long_Integer_Name)] := ...; > on the same basis (where this (evil) Increment both modifies its > argument, and returns a result). I realize I'm mixing Ada and C > notation there. Which is why it didn't get added to Ada 95, in spite of Robert Dewar's arguments in favor. The few cases where you do want functions with side-effects (random number generators being the prime example) can be written in Ada with a bit of extra work in the private part. > Perhaps. Who knows? I think it's mainly a cultural thing -- > everybody does it that way, so new programmers learn to do it that > way. No, it is cultural, but the language syntax does seem to have a very strong influence on the culture. One reason I believe that Algol 68 never succeeded was that the cultural imperitives implicit in the notation were in conflict. I once thought that translating the reserved* words into German, Dutch, or Czeck would have made people mcuh more comfortable with it. *Yes, in the standard they are not techically reserved, but did anyone have an implementation where they weren't? -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-09 0:00 ` Robert I. Eachus @ 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` Matthew Heaney 1997-05-12 0:00 ` Robert I. Eachus 0 siblings, 2 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-11 0:00 UTC (permalink / raw) Robert Eachus says <<Which is why it didn't get added to Ada 95, in spite of Robert Dewar's arguments in favor. The few cases where you do want functions with side-effects (random number generators being the prime example) can be written in Ada with a bit of extra work in the private part.>> It = allowing in out parameters in functions. The trouble is that Robert Eachus' claim is false. It is impossible to write the body of the random number generator specified in the Ada 95 RM efficiently in legitimate Ada 95 (the GNAT version has to use special GNAT specific attributes to get a decent implementation, though you could probably do the same with unchecked conversion in almost any implementation). <<No, it is cultural, but the language syntax does seem to have a very strong influence on the culture. One reason I believe that Algol 68 never succeeded was that the cultural imperitives implicit in the notation were in conflict. I once thought that translating the reserved* words into German, Dutch, or Czeck would have made people much more comfortable with it.>> I never saw anyone be uncomfortable with Algol-68 who used it. On the contrary in the few situations where it was available, it was widely used and liked (CDC 6000 series machines, and notably the Algol-68R implementation on ICL machines -- the latter implementation was widely used for both teaching and real projects, and in the British Journal of COmputing Survey in the early 70's, Algol-68 was named the ideal teaching language by over 90% of English universities (all of which had ICL machines due to government procurement pressures)). Many people posit all sorts of interesting theories about why Algol-68 "failed", but the simple fact of the matter is that Algol-68 succeeded where good compilers were available, and failed where they were not! <<*Yes, in the standard they are not techically reserved, but did anyone have an implementation where they weren't?>> That is technically confused. Algol-68 has two type styles for identifiers, represented as bold and normal in publication language, and signalled by some "stropping" convention in real compilers. Two typical stropping mechanisms are the use of upper case, and the use of quote marks, as in traditional Algol-60 compilers. Keywords and mode names (type names to the Ada folks) are in bold, and ordinary identifires are in normal font. The keywords ARE reserved as bold names, e.g. IF (or 'if') cannot be used as a mode name in Algol-68, but of course the identifier if in normal case can of course be used. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar @ 1997-05-11 0:00 ` Matthew Heaney 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` Robert I. Eachus 1 sibling, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-11 0:00 UTC (permalink / raw) In article <dewar.863365166@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: >Many people posit all sorts of interesting theories about why Algol-68 >"failed", but the simple fact of the matter is that Algol-68 succeeded >where good compilers were available, and failed where they were not! That's a weak argument, Robert. Many computer scientists (Tony Hoare, for example) define the "goodness" of a language (partly) as the ease of which a compiler can be written. If Algol-68 failed where there were "no good compilers," that could be interpreted to mean that Algol-68 was too complex a language to implement. This is the argument people use against Ada. I often see comparisons of PL/I, Algol-68, and Ada, in an argument that goes something like this: Big languages are bad. Ada is big. Therefore, Ada is bad, too. Obviously, I don't think lumping Ada in the same category as PL/I and Algol-68 is a fair comparison. Ada is big, but it is arguable whether Ada is complex. Those of us that actually use Ada know it has a coherent design, but that requires a fair amount of study to learn all of its nooks and crannies. (Example: many Ada programmers don't know that an array whose component subtype is Boolean comes with "or", "and", and "xor" as predefined operators.) (And by "fair amount of study," I only mean read at least a couple of books (Barnes and Cohen, say) from cover to cover. I've met few programmers that even do that; they usually just look something up when they're writing something that doesn't compile. Sadly, these programmers never learn all the features of the language that can make their life Really Easy, because they never try to learn the things they don't already know. But this problem isn't endemic to Ada: I've met many C programmers that never even got through K&R, which is all of 150 pages.) Perhaps compiler writers would care to comment on the difficulty of implementing an Ada compiler, and whether Ada is too complex. The author of Safer C, Les Hatton, argues that a language that has a lot of requests for interpretation (that means Ada, with its ARG) shouldn't be used to program safety-critical systems. I'm incredulous that he argues that C but not Ada can be made safe enough for that class of system - he advocates not using Ada at all - but what argument do we use as a refutation? Tony Hoare, in his Turing Award lecture, described Ada as having an "unnecessary plethora of features and notational conventions," and admonished not using the language "in its present state" (circa 1980) "where reliability is critical." If Tony Hoare says it, it must be so. Right? Thankfully, at least one author, David Watt (Programming Language Concepts and Paradigms) is sympathetic to Ada, and notes in his book that "Ada has done a good job of controlling its complexity." In fact, the school where he teaches, University of Glasgow, has selected Ada as the core language in which to teach its computer science students. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Matthew Heaney @ 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` Matthew Heaney 0 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-12 0:00 UTC (permalink / raw) Robert said >Many people posit all sorts of interesting theories about why Algol-68 >"failed", but the simple fact of the matter is that Algol-68 succeeded >where good compilers were available, and failed where they were not! Matthew said That's a weak argument, Robert. Many computer scientists (Tony Hoare, for example) define the "goodness" of a language (partly) as the ease of which a compiler can be written. If Algol-68 failed where there were "no good compilers," that could be interpreted to mean that Algol-68 was too complex a language to implement. Robert says This is complete nonsense. I would guess that it comes from complete lack of knowledge of Algol-68 and its history. Matthew says This is the argument people use against Ada. I often see comparisons of PL/I, Algol-68, and Ada, in an argument that goes something like this: Big languages are bad. Ada is big. Therefore, Ada is bad, too. Obviously, I don't think lumping Ada in the same category as PL/I and Algol-68 is a fair comparison. Robert says Now I *know* that you don't know Algol-68. Algol-68 is a FAR simpler language than Ada 95 or Ada 83, and is FAR easier to write a compiler for. I am speaking here from a position of knowing both languages well and having considerable experience in implementing both. If you assume that it is the case that Algol-68 is bad because it is too hard to write compilers from, then you would have to agree that Ada is even worse by this criterion. No one would tell you that it is simple to write Ada 95 compilers, on the contrary it is an extremely complex task. Though not significantly more complex than writing compilers for OO COBOL, Fortran 90, or C++. Actually these days, even C compilers are enormously complex beasts, because of the need to address complex optimization issues, so in the total scheme of things, the difficulty of writing the front end is by no means the tail that wags the dog when it comes to compiler complexity. The reason there were not more Algol-68 compilers, and that for example by comparison, Ada compilers flourished, is simple. There was not enough commercial pressure to generate these compilers. CDC put nearly a hundred person years into their Algol-68 development effort for the CDC 6600, but that was because a huge order in the Netherlands depended on it. Similarly, RRE put a lot of resources into Algol-68R because they wanted it for their own use, but overall, the commercial demand was simply too weak. In the end the "failure" of Algol-68 was a marketing issue, not a technical one. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Robert Dewar @ 1997-05-12 0:00 ` Matthew Heaney 1997-05-13 0:00 ` Jon S Anthony ` (3 more replies) 0 siblings, 4 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-12 0:00 UTC (permalink / raw) In article <dewar.863452575@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > The reason there were not more Algol-68 compilers, and that for example > by comparison, Ada compilers flourished, is simple. There was not enough > commercial pressure to generate these compilers...[snip]...In the end > the "failure" of Algol-68 was a marketing issue, not a technical one. I stand corrected. From what I've read, however, that language has been lambasted because of its too-frequent use of automatic type coercions. Opinion? Do you disagree with the argument that a language is "bad" - specifically, Ada - if it's difficult to implement a compiler for it? Do you disagree with Les Hatten who said that Ada shouldn't be used, because it has a "large number" of interpretation requests? Do you disagree with Tony Hoare's assessment that Ada should not be used for systems where high reliability is required? Inquiring minds want to know... -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Matthew Heaney @ 1997-05-13 0:00 ` Jon S Anthony 1997-05-13 0:00 ` Matthew Heaney 1997-05-14 0:00 ` Robert Dewar ` (2 subsequent siblings) 3 siblings, 1 reply; 120+ messages in thread From: Jon S Anthony @ 1997-05-13 0:00 UTC (permalink / raw) In article <mheaney-ya023680001205972045490001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: Robert sez: > > The reason there were not more Algol-68 compilers, and that for example > > by comparison, Ada compilers flourished, is simple. There was not enough > > commercial pressure to generate these compilers...[snip]...In the end > > the "failure" of Algol-68 was a marketing issue, not a technical one. Well, yes, but this is more an explanation based on a symptom. The real real reason is that A68 used a real formal specification based on W-grammars. If not the implementors, then certainly the joe-average person looking into the language found this more or less impenetrable => can't understand what it is => no hope of understanding how to use it => no desire to use it => no demand for it => no commercial pressure for compilers. Rather unfortunate really... /Jon -- Jon Anthony Organon Motives, Inc. Belmont, MA 02178 617.484.3383 jsa@organon.com ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-13 0:00 ` Jon S Anthony @ 1997-05-13 0:00 ` Matthew Heaney 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Robert Dewar 0 siblings, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-13 0:00 UTC (permalink / raw) In article <JSA.97May13165926@alexandria>, jsa@alexandria (Jon S Anthony) wrote: >> > The reason there were not more Algol-68 compilers, and that for example >> > by comparison, Ada compilers flourished, is simple. There was not enough >> > commercial pressure to generate these compilers...[snip]...In the end >> > the "failure" of Algol-68 was a marketing issue, not a technical one. > >Well, yes, but this is more an explanation based on a symptom. The >real real reason is that A68 used a real formal specification based on >W-grammars. If not the implementors, then certainly the joe-average >person looking into the language found this more or less impenetrable >=> can't understand what it is => no hope of understanding how to use >it => no desire to use it => no demand for it => no commercial >pressure for compilers. Here's another explanation: "The real question is why [Algol-68] did not come into more widespread use, and the answer here is simple enough: because it was not implemented widely enough, or soon enough. And the reason for that is that implementation was too hard, and the reason for that was on account of a relatively small number of troublespots, not inherently necessary for the basis principles of the language and certainly not for its orthogonality." Quoted from "A History of Algol-68," by C. H. Lindsey, chapter II in the book History of Programming Languages Thomas J. Bergin Richard G. Gibson ACM Press/Addison-Wesley, 1996 ISBN 0-201-89502-1 -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-13 0:00 ` Matthew Heaney @ 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Robert Dewar 1 sibling, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Matthew said <<"The real question is why [Algol-68] did not come into more widespread use, and the answer here is simple enough: because it was not implemented widely enough, or soon enough. And the reason for that is that implementation was too hard, and the reason for that was on account of a relatively small number of troublespots, not inherently necessary for the basis principles of the language and certainly not for its orthogonality.">> quoting Charles. In reading the above paragraph, you need to put it into the right perspective, which in this case is Algol-60. There is no question that a minimal non-optimizing A68 compiler is hugely more difficult to write than an A60 compiler, and as I noted in my previous note, doomed efforts to write quick-and-dirty compilers in people's spare time. There were some funded university efforts in Europe, but another factor was that here in the US, despite a lot of interest, NSF has never been interested in funding what it sees as basically engineering efforts -- and that has meant that compiler development in universities here has floundered compared with the situation in Europe (it is no accident that Algol-68R and Algol-68S both came out of British universities). I actually disagree with Charles that the trouble spots were so significant. I think it was more a matter of overall complexity than specific trouble spots, but that's a disagreement of degree -- as with all languages, there are trouble spots. But say compared to Ada, where relatively few features dominate the implementation complexity severely (generics, private, discriminants), I think the situation in A68 is MUCH simpler and MUCH more uniform. It is interesting that the trouble spots in Ada-95 are all Ada-83 things. Tuck said to me once that the hard part of implementing Ada -95 was Ada-83, and I know exactly what he means. For the most part, Ada 95 is not significantly harder to implement than Ada 83. Probably finalization is the one significant exception to this generalization. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-13 0:00 ` Matthew Heaney 1997-05-14 0:00 ` Robert Dewar @ 1997-05-14 0:00 ` Robert Dewar 1 sibling, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Jon said >Well, yes, but this is more an explanation based on a symptom. The >real real reason is that A68 used a real formal specification based on >W-grammars. If not the implementors, then certainly the joe-average >person looking into the language found this more or less impenetrable >=> can't understand what it is => no hope of understanding how to use >it => no desire to use it => no demand for it => no commercial >pressure for compilers. For the implementors, the formal report was great. I only wish that I had something that easy to follow precisely for other languages. True, there was a HUGE learning barrier, and only a few dozen people ever got to the point of really knowing this document well (I was one, but then I was chair of WG2.1, and chair of the Algol-68 mainteance committee for a while, so I should hope so :-) It was definitely NOT a document for beginners, or even reasonably experienced experts. But people did not learn Algol-68 from the RR anyway. They learned it, for example, from the very nice 70 page yellow book that came with the Algol-68R compiler -- an easy evening's read -- I only wish there were something equivalent for Ada ... But people do not really get interested in a language until there are implementations around, and implementations only appear if there are commercial interests in funding such implementations. Algol-68 was, as are most modern languages, not the kind of language that someone can write a compiler for in their spare time -- several tried and failed, although a couple of the non-funded compilers (algol-68S and algol-68C -- the latter from Steve Bourne of the Bourne shell -- that's why the Bourne shell is a68 like) were quite successful. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Matthew Heaney 1997-05-13 0:00 ` Jon S Anthony @ 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 3 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Matthew said <<I stand corrected. From what I've read, however, that language has been lamtive to Ada. of its too-frequent use of automatic type coercions. Opinion?>> A good example of reading other people's ill-informed assessments. If you see someone say this about Algol-68, it means they don't know much about Algol-68, or, more likely, in an attempt to impress their friends and neighbours they are quoting opinions which they do not understand. I am willing to bet that Matthew is quite unaware of what type coercions mean in Algol-68. For example a := b; where a and b are integer variables, is considered a type conversion (mode coercion) in Algol-68, since the right side must be converted from ref int to int by dereferencing -- gosh isn't it awful a language having automatic type conversions like that (note that Bliss actually agrees in this case, but it is unusual in its opinion). Do NOT assume that famous people know what they are talking about when it comes to programming languages. Many well known people in the field break my rule about not criticizing languages without having written a substantial amount of code -- and they break it spectacularly, often criticizing features that just don't exist. A few years ago, I reviewed a proposal from some Canadian Professor which dismissed Algol-68 on the silly grounds that Matthew mentions above (too may type coercions), and gave as an example the following where a is ref ref int a := 4; is terrible, because it automatically deferences a and therefore you don't know what variable is being assigned. There is only one problem with this. Algol-68 has NEVER allowed automatic cooercion on the left side of an assignment, so the above is illegal (you have to write an explicit conversion, analogous to the use of .all in Ada, or * in C) An irony is that I know exactly where he got this from, there is a well known paper by a very well known author, who is considered an expert in programming languages, which presents EXACTLY this wrong example. Needless to say, I gave the proposal a very low rating, anyone who simply adopts other people's opinion uncritically as their own is unlikely to make a good scientific investigator! <<Do you disagree with the argument that a language is "bad" - specifically, Ada - if it's difficult to implement a compiler for it?>> As I noted previously, writing any compiler is hard. Writing a good compiler for C is difficult. If you think this means that a language is bad, then all languages are bad. Yes, it is true that modern languages like C++, Fortran-90, OO COBOL, and Ada 95 are harder to compile, but so what. That's what computers are for -- doing work that we would have to do ourselves otherwise. These comprehensive languages do a lot for us that we would have to do for ourselves <<Do you disagree with Les Hatten who said that Ada shouldn't be used, because it has a "large number" of interpretation requests?>> Of course I disagree, Les Hatten does not know what he is talking about. In fact the extent to which the standard has needed interpreting is very small. Almost all of the AI's for Ada 83, all of which are resolved for Ada 95, are for marginal issues that affect few or no programmers. Furthermore, other languages if anything have MORE interpretations that have to be issued (I wonder if Les has for example read the JOD for COBOL) <<Do you disagree with Tony Hoare's assessment that Ada should not be used for systems where high reliability is required?>> This is not necessarily Tony Hoare's assessment today, and if you read his Turing award lecture carefully , you will find it is not so absolute. In particular, he specifically notes that a subset of Ada *would* be a suitable vehicle. Since all high reliability systems using Ada do in fact use a well chosen subset, I see no conflict here. Indeed when I talked with Tony some years ago, he expressed frustration that his lecture had been taken as condemning Ada out of hand. He was simply using it as an example of some trends in language design to be worried about, and he felt that people had misread the talk if they felt it was wholly negative to Ada. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Matthew Heaney 1997-05-13 0:00 ` Jon S Anthony 1997-05-14 0:00 ` Robert Dewar @ 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 3 siblings, 0 replies; 120+ messages in thread From: Nick Roberts @ 1997-05-14 0:00 UTC (permalink / raw) Matthew Heaney <mheaney@ni.net> wrote in article <mheaney-ya023680001205972045490001@news.ni.net>... [...] > Do you disagree with the argument that a language is "bad" - specifically, > Ada - if it's difficult to implement a compiler for it? > > Do you disagree with Les Hatten who said that Ada shouldn't be used, > because it has a "large number" of interpretation requests? > > Do you disagree with Tony Hoare's assessment that Ada should not be used > for systems where high reliability is required? > > Inquiring minds want to know... Ada is a bit like the Mustang of the world of Second World War fighter planes. This aircraft was described as the 'Rolls Royce of the air'. It was a fabulous plane, and it represented (more or less) the apex of the development of that particular technology. But, then, along came jet fighters, and it was totally obsolete. In the same way, I'm sure that no 'traditional' programming language will ever be invented which is significantly better than Ada (or C++, or one of the various other languages which are at a similar level), because very soon a new generation of programming environments will become prevalent which work in a different way. [These are languages which tend (mostly) to be programmed directly by other programs, and only indirectly by humans. I could go on about this at length, but this newsgroup is probably not the right place.] The point is, there's no reason not to use Ada (et al) because there's no real alternative, and there never will be. In 300 years time from now, (the base subsystems of) spaceships will still be programmed in Ada (or C++ or whatever), because there will never have been the need to supercede the language or the software. People still use tables and chairs which were designed centuries ago; the designs are as good today as they were then: good enough. However, in 10 years time, new software will mostly be created using Super AI Intuitive Visual Java Workshop (or whatever), and actually writing source code at all will become unusual. Is Ada a bad language because it is complicated to implement? No: the goodness of a language and the ease of its implementation are two totally different things. However, a language may fail in the marketplace if it is difficult to implement. Should Ada not be used because its standard attracts a large number of implementation requests? One may be wary of the quality of implementations of the language; but this does not preclude the possibility of good implementations. The language may have benefits to offer which weigh in its favour. As for Mr. Hoare's assessment of Ada. How many (real) high-reliability systems did he write? Is he really qualified to make judgements of this kind? If software I have written in the past fails, a number of service personnel stand to lose their lives as a result. I would not have chosen Ada to write this software (and I did have the choice, then) if I had felt it would put them (and the efficacy of part our defence forces) at risk. Nick. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Matthew Heaney ` (2 preceding siblings ...) 1997-05-14 0:00 ` Nick Roberts @ 1997-05-14 0:00 ` Robert Dewar 1997-05-15 0:00 ` W. Wesley Groleau (Wes) 3 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) One more comment <<Do you disagree with Les Hatten who said that Ada shouldn't be used, because it has a "large number" of interpretation requests?>> Very often people who make this criticism simply count the number of interpretation requests. That's truly stupid, since a large number of them are presentation comments (people think there should be a comma here, or that something should be in a different type font etc). ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-14 0:00 ` Robert Dewar @ 1997-05-15 0:00 ` W. Wesley Groleau (Wes) 0 siblings, 0 replies; 120+ messages in thread From: W. Wesley Groleau (Wes) @ 1997-05-15 0:00 UTC (permalink / raw) Robert Dewar wrote: > <<Do you disagree with Les Hatten who said that Ada shouldn't be used, > because it has a "large number" of interpretation requests?>> > > Very often people who make this criticism simply count the number of > interpretation requests. That's truly stupid, since a large number of > them are presentation comments (people think there should be a comma > here, or that something should be in a different type font etc). Which could be construed as an indication that Ada people are far more careful about details than those in groups with fewer such comments! :-) ---------------------------------------------------------------------- Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA Senior Software Engineer - AFATDS Tool-smith Wanna-be w w g r o l at p s e u l t 0 1 dot f w dot h a c dot c o m SPAM should be sent to I.want.one@mailbombs.for.idiots.org If you don't want to pay $500 (see 47 USC 227), don't send it here. ---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` Matthew Heaney @ 1997-05-12 0:00 ` Robert I. Eachus 1997-05-13 0:00 ` Robert Dewar 1 sibling, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-12 0:00 UTC (permalink / raw) In article <dewar.863365166@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes: > It = allowing in out parameters in functions. The trouble is that > Robert Eachus' claim is false. It is impossible to write the body > of the random number generator specified in the Ada 95 RM > efficiently in legitimate Ada 95 (the GNAT version has to use > special GNAT specific attributes to get a decent implementation, > though you could probably do the same with unchecked conversion in > almost any implementation). I guess we have different definitions of efficiency. Since for any decent random number generator the generator parameter will be a record that should be passed by reference, the fact that "pure" Ada may require the generator object to be on a heap (so the pointer can be passed as an in parameter) has no effect on the efficiency of the call to Random. Any overhead occurs in the creation and deletion of generator objects, which usually occurs once per program. > Many people posit all sorts of interesting theories about why > Algol-68 "failed", but the simple fact of the matter is that > Algol-68 succeeded where good compilers were available, and failed > where they were not! No. I never had access to the ICL compiler but I did use the RRE compiler and even looked into porting it to Multics. But now that you mention it, it was speakers of American English that found the usage jarring, so maybe the usages were more comfortable to the British. One of the most jarring was pragmat, and we have so little trouble with pragma. > That is technically confused. Algol-68 has two type styles for > identifiers, represented as bold and normal in publication > language, and signalled by some "stropping" convention in real > compilers. Two typical stropping mechanisms are the use of upper > case, and the use of quote marks, as in traditional Algol-60 > compilers. Aarrgh! I tried to use the quote stropping mode ONCE. Still gives me nightmares. Recognizing only the UPPER CASE reserved words as reserved was common, but it made for a style that only Mike Feldman could love. ;-) I guess I should have asked if anyone ever used a mode other than treating the keywords as reserved. (It has been awhile, but I'm pretty sure that was common with Algol-68R.) > Keywords and mode names (type names to the Ada folks) are in bold, > and ordinary identifires are in normal font. The keywords ARE > reserved as bold names, e.g. IF (or 'if') cannot be used as a mode > name in Algol-68, but of course the identifier if in normal case > can of course be used. Ah, one other difference, that may have made all the difference. At the time, in the US, most high-speed printers were run with 48-character (all upper-case) print chains and even medium speed printers were often 7 or 9 pin printers with no usable lower case. Using upper case as the only stropping was simply not on. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` Robert I. Eachus @ 1997-05-13 0:00 ` Robert Dewar 1997-05-14 0:00 ` Nick Roberts 0 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-13 0:00 UTC (permalink / raw) Robert Eachus claimed that there was no problem in writing a random number generator of the kind specified in the RM, and followed up my query about this with: << I guess we have different definitions of efficiency. Since for any decent random number generator the generator parameter will be a record that should be passed by reference, the fact that "pure" Ada may require the generator object to be on a heap (so the pointer can be passed as an in parameter) has no effect on the efficiency of the call to Random. Any overhead occurs in the creation and deletion of generator objects, which usually occurs once per program.>> Which makes it clear that he is quite happy with a random number generator that implicitly uses the heap -- and, he knows this surely, but forgot to mention it -- controlled types, since you have to be ssure that these implicitly allocated generators are properly freed when no longer needed. So here we have (a) implicit use of the heap, which may be a real problem in an environment which wants to avoid heap use completely, and in any case is problematic. For example, it means that pragma Restrictions (No_Implicit_Heap_Allocations); will cause the random number to be unavalable. (b) you drag in all the support stuff for controlled, and also introduce implicit finalization which you do not expect. This finalization could for example increase the latency on ATC at a critical point. All this because the language does not allow in-out parameters on functoin arguments. At least for GNAT, this is academic, because we certainly do not use the heap for random number generators (despite what Robert Eachus says, I don't consider this acceptable for a second). Instead we write the body using 'Unrestricted_Access which allows us to get the equivalent of in-out parameters in functions, although certainly not in a portable manner. I wonder what other Ada 95 compilers do, someone want to check Object Ada -- this is one case where they cannot be using the GNAT routine, since as far as I know they do nt provide Unrestricted_Access. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-13 0:00 ` Robert Dewar @ 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 0 siblings, 1 reply; 120+ messages in thread From: Nick Roberts @ 1997-05-14 0:00 UTC (permalink / raw) Robert Dewar <dewar@merv.cs.nyu.edu> wrote in article <dewar.863525543@merv> that the Ada 95 standard forces the heap to be used in the implementation of the standard random number generator packages, and suggests that this would have been avoided if Ada allowed 'in out' parameters in functions. This is true, but it would also have been avoided if the standard had simply specified procedures for obtaining the random numbers instead of functions. I believe it is a useful paradigm to always (or almost always) use procedures where there are side effects. However, is it not possible to implement Generator as a general access type, and then cause it to access an aliased variable (thus avoiding use of the heap)? Nick. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-14 0:00 ` Nick Roberts @ 1997-05-14 0:00 ` Robert Dewar [not found] ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com> 0 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Nick says <<This is true, but it would also have been avoided if the standard had simply specified procedures for obtaining the random numbers instead of functions. I believe it is a useful paradigm to always (or almost always) use procedures where there are side effects. However, is it not possible to implement Generator as a general access type, and then cause it to access an aliased variable (thus avoiding use of the heap)?>> To the first para, this seems another example of forcing an inconvenient notation as a result of blindly following rules. There are many cases where functions with side effects are the most appropriate and convenient way of expressing things. As to the second para, the answer is no. If you don't see why, just try it and you will see (basically there is nowhere except the heap to allocate the generator). ^ permalink raw reply [flat|nested] 120+ messages in thread
[parent not found: <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>]
* Re: Not intended for use in medical, [not found] ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com> @ 1997-05-16 0:00 ` Robert A Duff 1997-05-16 0:00 ` Robert I. Eachus 1997-05-16 0:00 ` Robert Dewar 1 sibling, 1 reply; 120+ messages in thread From: Robert A Duff @ 1997-05-16 0:00 UTC (permalink / raw) In article <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>, Nick Roberts <Nick.Roberts@dial.pipex.com> wrote: >Quite right. I was forgetting that as the packages >Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are >grandchildren of the package Ada, which is declared as pure, they must be >pure also, ... There is no such rule. Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are in fact *not* pure. AARM-A.5.2(27.a) explains why. Note that all library units are (direct or indirect) children of Standard. And Standard is declared Pure. So the (nonexistent) rule you stated above wouldn't quite work -- good thing it's not in the RM! ;-) >...(Is this it, or is there some other reason >that I have missed?) As Robert said: Try to write the code using only portable features -- I think you'll find that there's nowhere to put the Generator data, except in the heap. (Actually, I suppose I should say "a heap" -- you could create your own data structure that acts as a heap.) No fair using Unchecked_Conversion to convert an Address (or an access-to-constant) to an access-to-variable type -- you could do it that way on some compilers, but it's not formally portable. Actually, the semantics of GNAT's 'Unrestricted_Access are defined as Unch_Conv of a 'Address -- which of course doesn't really "define" the semantics at all, since the semantics of such an unchecked conversion is not defined. An 'in' parameter is a constant. If you succeed in modifying one, you are necessarily doing something undefined! - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-16 0:00 ` Robert A Duff @ 1997-05-16 0:00 ` Robert I. Eachus 1997-05-18 0:00 ` Nick Roberts 0 siblings, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-16 0:00 UTC (permalink / raw) In article <EAA6so.JAz@world.std.com> bobduff@world.std.com (Robert A Duff) writes: > As Robert said: Try to write the code using only portable features -- I > think you'll find that there's nowhere to put the Generator data, except > in the heap. (Actually, I suppose I should say "a heap" -- you could > create your own data structure that acts as a heap.) Yep. I pointed out to Robert Dewer in a back-channel discussion, but a point which definitely belongs here, that the real problem comes from the implicit assumption that programs that create lots of generators are somehow "normal." One generator is very normal, two or three is even understandable but, there is not enough entropy in the environment to make dozens of PRNGs meaningful absent access to a source of true random bits. In point of fact for most RNGs, creating more than, say, a dozen generators will make your results very suspect. For the generator in GNAT, you can create a set of thousands of independent generators using the standard interface. But it ain't easy. If you need to do it. Create a random integer from a source of entropy outside the program, or just use a default generator and reset it using the clock. Now use a sequence of integers to seed your generators: Seed: Integer := ...; Generators: array (Integer range 1..10000) of Ada.Numerics.Float_Random.Generator; ... if Seed > Integer'Last - Generators'Last then Seed = Seed + Integer'First; end if; --technically this introduces a bias but a very slight one... for I in Generators'Range loop Reset(Generators(I),Seed + I); end loop; Okay, now you can generate away knowing that no two of your generators will create a correlated sequence, or a sequence that correlates with a lead or lag. (Unless you use tens of millions of values from each generator.) > No fair using Unchecked_Conversion to convert an Address (or an > access-to-constant) to an access-to-variable type -- you could do > it that way on some compilers, but it's not formally portable. Having gone through the why, it is perfectly reasonable to make the Generator parameter an index into a small set of actual generators in the body of the generator package. (Use index mod N for some small N if you don't want to worry people whose programs are junk. However, you had better make those generators protected objects in a tasking environment.) > Actually, the semantics of GNAT's 'Unrestricted_Access are defined > as Unch_Conv of a 'Address -- which of course doesn't really > "define" the semantics at all, since the semantics of such an > unchecked conversion is not defined. > An 'in' parameter is a constant. If you succeed in modifying one, you > are necessarily doing something undefined! Worse than that. Since you are actually accessing the Generator through two different paths (an in parameter and an access type), this is formally a bounded error. see 6.2(12). Of course it is harmless in this case--the compiler vendor provides the package and knows what the behavior is. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-16 0:00 ` Robert I. Eachus @ 1997-05-18 0:00 ` Nick Roberts 1997-05-18 0:00 ` Matthew Heaney 0 siblings, 1 reply; 120+ messages in thread From: Nick Roberts @ 1997-05-18 0:00 UTC (permalink / raw) Robert I. Eachus <eachus@spectre.mitre.org> wrote in article <EACHUS.97May16192037@spectre.mitre.org> some interesting observations about multiple random number generators. Many thanks for the replies I've had to this post. I did indeed have a serious misunderstanding of the purity of packages. I see my mistake: an impure package cannot have a pure child (not the other way around). I've had another close look at the Float_Random and Discrete_Random packages in the RM. I think I see what people are driving at about having to use the heap (or 'a heap'). I was thinking that one could implement the type Generator as a general access type (in fact a controlled type with a general access component), and then have just one generator declared directly in the package body, and cause all objects of type Generator to point to it. However, this would violate the independence of the generators, something which the standard insists on. It is interesting to note that if a program creates many generators seeded by the clock all at (very nearly) the same time, it runs the risk (depending on the resolution of the clock) of all those generators (or many of them) being seeded with the same seeds, and therefore generating exactly the same sequences of numbers. It is on this issue which Robert Eachus was writing (I think). Are there any practical situations where this might be a problem? Additionally, are there any practical situations where the fact that the standard random packages must be implemented using the heap is a significant problem? Once again, very many thanks for the replies, which I have found most illuminating. Nick. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-18 0:00 ` Nick Roberts @ 1997-05-18 0:00 ` Matthew Heaney 1997-05-19 0:00 ` Robert I. Eachus 1997-05-19 0:00 ` Robert A Duff 0 siblings, 2 replies; 120+ messages in thread From: Matthew Heaney @ 1997-05-18 0:00 UTC (permalink / raw) In article <01bc63a2$e3e1a940$LocalHost@xhv46.dial.pipex.com>, "Nick Roberts" <Nick.Roberts@dial.pipex.com> wrote: >It is interesting to note that if a program creates many generators seeded >by the clock all at (very nearly) the same time, it runs the risk >(depending on the resolution of the clock) of all those generators (or many >of them) being seeded with the same seeds, and therefore generating exactly >the same sequences of numbers. It is on this issue which Robert Eachus was >writing (I think). Are there any practical situations where this might be a >problem? Funny you should bring that up. We just wrote a small application with 10 tasks, where each one wakes up every 5 seconds to check a randomly-generated temperature. In spite of the fact that each task had its own generator, each one yielded the same value. This was undoubtedly caused by the fact the each generator had been (automatically) seeded with the same time. Here's what we did to solve the problem, but it didn't work. Instead of each task having its own generator, we made one generator, and wrapped it in a protected object. When each task woke up, it called a protected function that returned the random value: protected Generator is function Random return Temperature; private G : Random_Temperatures.Generator; end; protected body Generator is function Random return Temperature is begin return Random_Temperatures.Random (G); end; end; I assumed each invokation of Generator.Random would return a different random number (or at least random numbers evenly distributed about the range of temperature), but this isn't so. Every 5 seconds, all 10 tasks would wake up and call the protected object. I thought that these 10 invokations would generate different random values, but all 10 tasks received the same random value. The value would change every 5 seconds, but all 10 tasks would get that same value. This was my first time using a protected object, and perhaps I have misused it somehow. Maybe a state-changing protected procedure would force a new random number to be generated when invoked, and it was incorrect to use a protected function. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-18 0:00 ` Matthew Heaney @ 1997-05-19 0:00 ` Robert I. Eachus 1997-05-19 0:00 ` Matthew Heaney 1997-05-19 0:00 ` Robert A Duff 1 sibling, 1 reply; 120+ messages in thread From: Robert I. Eachus @ 1997-05-19 0:00 UTC (permalink / raw) In article <mheaney-ya023680001805971550190001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes: > Funny you should bring that up. We just wrote a small application > with 10 tasks, where each one wakes up every 5 seconds to check a > randomly-generated temperature. In spite of the fact that each > task had its own generator, each one yielded the same value. This > was undoubtedly caused by the fact the each generator had been > (automatically) seeded with the same time. No. First read A.5.2(28). There is a single state which all generators are implicitly initialized to. This was really chosen on the assumption that any non-trivial user would use one of the Reset functions. An alternative would have been to have each new generator start in a state uncorrelated with any other, but as my previous message pointed out that is next to impossible for some generators. At this point, I think that the best idea would have been to require that the generators be set before being called by calling Reset and otherwise raising Program_Error. Read what I wrote in the previous article for one solution to this problem. Generate a seed from the clock--you can use the explicit generator that does this, but: Seed: Integer := Integer(Float(Seconds(Calendar.Clock) * 1000)) is probably enough. Now pass Seed, Seed+1, Seed+2, etc. to the appropriate version of Reset. Another solution is below: > Here's what we did to solve the problem, but it didn't work. > Instead of each task having its own generator, we made one > generator, and wrapped it in a protected object. When each task > woke up, it called a protected function that returned the random > value: > protected Generator is > function Random return Temperature; > private > G : Random_Temperatures.Generator; > end; > protected body Generator is > function Random return Temperature is > begin > return Random_Temperatures.Random (G); > end; > end; > I assumed each invokation of Generator.Random would return a > different random number (or at least random numbers evenly > distributed about the range of temperature), but this isn't so. > Every 5 seconds, all 10 tasks would wake up and call the protected > object. I thought that these 10 invokations would generate > different random values, but all 10 tasks received the same random > value. The value would change every 5 seconds, but all 10 tasks > would get that same value. Burned by the side effects of Random! The problem is that you have to access the generator from inside a protected procedure or entry since you can't afford to have several tasks accessing a function with side effects at the same time. Try: function Generator return Temperature; ... and in the body: protected Generator is procudure Protected_Random(Temp: out Temperature); private G : Random_Temperatures.Generator; end; function Random return Temperature is Temp: Temperature; begin Generator.Random(Temp); return Temp; end Random; protected body Generator is procedure Protected_Random(Temp: out Temperature) is begin Temp := Random_Temperatures.Random (G); return; end; end; -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-19 0:00 ` Robert I. Eachus @ 1997-05-19 0:00 ` Matthew Heaney 1997-05-20 0:00 ` Nick Roberts 0 siblings, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-19 0:00 UTC (permalink / raw) In article <EACHUS.97May19155433@spectre.mitre.org>, eachus@spectre.mitre.org (Robert I. Eachus) wrote: > Read what I wrote in the previous article for one solution to this >problem. Generate a seed from the clock--you can use the explicit >generator that does this, but: > > Seed: Integer := Integer(Float(Seconds(Calendar.Clock) * 1000)) > > is probably enough. Now pass Seed, Seed+1, Seed+2, etc. to the >appropriate version of Reset. Another solution is below: My post about initializing the discriminant of task that is a componant of an array was motivated by this problem. The idea was to use the task id - which was guaranteed to be unique - as the seed of the random number generator: task type T (Id : Integer) is entry E; end T; task body T is G : Generator; begin Reset (G, Initiator => Id); ... This solves the problem of using the clock as a seed, because there's no guarantee that all tasks will read a different time value (or at least time values that differ by more than 1 second - very unlikely). Robert Dewar is definately correct on this one: we need functions with in out mode parameters, in spite of what the pundits say. If function Random had had an in out parameter, I would have known at compile time that a protected function was illegal (and wouldn't work). Functions without side effect look great on paper, until you try to do real programming with that restriction. Robert's painful experience implementing the random number generator in GNAT is all the proof one needs to justify side-effect producing functions, and modifying the syntax to call out that fact. And my own experience - innocently calling Random from a protected function (compiles fine, but doesn't work) - is yet more evidence. The whole point of Ada is to detect "the things that won't work" at compile time. So now, before implementing a protected function, I have to make sure that any functions I call aren't causing side effect. With the current syntax, I can't determine that without reading the body of the function! It's not unlike the template model in C++. Stroustrup seems to have used parametric polymorphism as the model, and it looks great on paper, until you try to implement it in a real compiler. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-19 0:00 ` Matthew Heaney @ 1997-05-20 0:00 ` Nick Roberts 1997-05-20 0:00 ` Matthew Heaney 0 siblings, 1 reply; 120+ messages in thread From: Nick Roberts @ 1997-05-20 0:00 UTC (permalink / raw) Matthew Heaney <mheaney@ni.net> wrote in article <mheaney-ya023680001905971935290001@news.ni.net>... [...] > Robert Dewar is definately correct on this one: we need functions with in > out mode parameters, in spite of what the pundits say. If function Random > had had an in out parameter, I would have known at compile time that a > protected function was illegal (and wouldn't work). > > Functions without side effect look great on paper, until you try to do real > programming with that restriction. Robert's painful experience > implementing the random number generator in GNAT is all the proof one needs > to justify side-effect producing functions, and modifying the syntax to > call out that fact. And my own experience - innocently calling Random from > a protected function (compiles fine, but doesn't work) - is yet more > evidence. > > The whole point of Ada is to detect "the things that won't work" at compile > time. So now, before implementing a protected function, I have to make > sure that any functions I call aren't causing side effect. With the > current syntax, I can't determine that without reading the body of the > function! The other extreme would be to totally disallow side effects in functions (by not allowing them to write to outside variables, or to do I/O, or to call other subprograms which have (or may have) side-effects). For most functions (Sin, Cos, Tan, etc.) this would be no problem. For a function such as Random, it would be impossible (a procedure would have to be used instead). I'm not really advocating this idea: I recognise that it would be just too impractical in some situations. (R. D. would presumably burst a blood vessel! :-) However, note that the widespread compiler-evaluation of functions would be possible, if they could all be guaranteed not to have side-effects (and provided their evaluation did not take too long). Does anyone know of any Ada compiler which performs this optimisation for subprograms which can be deduced to be 'independent' (definitely having no side-effects)? Would such an optimisation be useful? Would it be practicable? Wouldn't it be helpful if the compiler gave a warning whenever a non-independent function was declared inside a protected object? Comments invited! Nick. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-20 0:00 ` Nick Roberts @ 1997-05-20 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Dale Stanbrough 0 siblings, 1 reply; 120+ messages in thread From: Matthew Heaney @ 1997-05-20 0:00 UTC (permalink / raw) In article <01bc6562$cb02f3e0$LocalHost@xhv46.dial.pipex.com>, "Nick Roberts" <Nick.Roberts@dial.pipex.com> wrote: >Does anyone know of any Ada compiler which performs this optimisation for >subprograms which can be deduced to be 'independent' (definitely having no >side-effects)? The word is "pure." And GNAT has a pragma (pragma Pure, I think), so that you can tell the compiler that a function has no side effect. >Wouldn't it be helpful if the compiler gave a warning whenever a >non-independent function was declared inside a protected object? Yes, it certainly would... -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-20 0:00 ` Matthew Heaney @ 1997-05-21 0:00 ` Dale Stanbrough 0 siblings, 0 replies; 120+ messages in thread From: Dale Stanbrough @ 1997-05-21 0:00 UTC (permalink / raw) Matthew Heaney= writes: "That way I could say [about selectors] The_Stack.Top := 5; instead of Update_Top (The_Stack, To => 5); The idea is to let the compiler do the automatic defereferencing (a selector "invokation" could be an lvalue or an rvalue): The_Stack.Top := The_Stack.Top + 1;" The problem with selectors such as this is when you have concurrency. To provide atomicity of operations with selectors requires the client of an abstraction to provide the appropriate guards. If you have the update encapsulated (as in Update_Top), you can centralise the locking protocols in the abstraction. Dale ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-18 0:00 ` Matthew Heaney 1997-05-19 0:00 ` Robert I. Eachus @ 1997-05-19 0:00 ` Robert A Duff 1 sibling, 0 replies; 120+ messages in thread From: Robert A Duff @ 1997-05-19 0:00 UTC (permalink / raw) In article <mheaney-ya023680001805971550190001@news.ni.net>, Matthew Heaney <mheaney@ni.net> wrote: >This was my first time using a protected object, and perhaps I have misused >it somehow. Maybe a state-changing protected procedure would force a new >random number to be generated when invoked, and it was incorrect to use a >protected function. That's right. Protected functions aren't supposed to modify state like that, since multiple protected functions (on the same protected object) can execute in parallel. I don't know if that's the bug causing your trouble, but is *a* bug. As you say -- use a protected procedure. If you insist on function-call notation, then wrap *that* in (normal) function. - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, [not found] ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com> 1997-05-16 0:00 ` Robert A Duff @ 1997-05-16 0:00 ` Robert Dewar 1 sibling, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-16 0:00 UTC (permalink / raw) Nick asks/says <<Would you care to give one or two examples?>> (of functions with useful side effects) No, I don't think so, this horse has been beaten to death too many times to be worth discussing any more. Well I will give just one phrase, memo functions, that should be enough! Note that this issue was discussed in the very early stages of the language design, and everyone agrees that there is a necessity in a language like Ada to permit functions with side effects. The issue that was discussed was whether to distinguish between functions without side effects, and value returning procedures with side effects. But even that attempt fails, because you can have functions that at a conceptual interface level are pure, but their implementations require side effects (memo functions are the canonical example). Note that it will work just fine to give the pragma Pure_Function in GNAT for a memo function, even though it has side effects. <<Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are grandchildren of the package Ada, which is declared as pure, they must be pure also, and pure packages are not allowed to have any state (such as internal generators). Silly me. (Is this it, or is there some other reason that I have missed?)>> The Pure is completely irrelevant here, the problem has no solution in pure Ada without using the heap even if you did not have pragma Pure. Furthermore the idea that children of a pure package must be pure is a pretty serious misconception about the whole structure of child packages. It is of course the other way round, you cannot have pure children of an impure parent, but OF COURSE you can have impure children of pure parents -- what would make you think this was not allowed. <<Quite right. I was forgetting that as the packages Ada.Numerics.Float_Random and Ada.Numerics.Discrete_Random are grandchildren of the package Ada, which is declared as pure, they must be pure also, and pure packages are not allowed to have any state (such as internal generators). Silly me. (Is this it, or is there some other reason that I have missed?)>> As above, you are confused. <<However, I did spot that the RM95 has "pragma Pure(Ada.Numerics);" in the Ada.Numerics package, which seems odd to me, since Ada.Numerics must be pure anyway (because it's a child of Ada). Why the extra pragma Pure?>> If you see something that seems odd to you in the RM, it is quite likely that, as in this case, it corresponds to a misunderstanding on your part. As per above, there is no extra Pure, and the Pure here is important. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-07 0:00 ` Robert Dewar 1997-05-08 0:00 ` John G. Volan 1997-05-08 0:00 ` Not intended for use in medical, Robert A Duff @ 1997-05-08 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert Dewar ` (2 more replies) 2 siblings, 3 replies; 120+ messages in thread From: Kaz Kylheku @ 1997-05-08 0:00 UTC (permalink / raw) In article <dewar.863062734@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Robert Duff said > ><<I agree (except I'd remove "perhaps"). There's nothing wrong with >having short-hand notations like "++" and "+=".>> > >There is something potentially wrong, which is that compact operation >notations like this are most happy with short identifier names, as in > > a++; > >not nearly so pretty is > > Average_Daily_Rate_Of_Pay++; > >and indeed if you speak the above, it comes out as a joke, people laugh. > >Well of course this is not the only reason that C programmers so often >favor short cryptic identifier names (and of course there is nothing in C >which requires them), but it is a contributing factor! There are all kinds of good reasons; those short cryptic identifiers offer better readability. Of course, Average_Daily_Rate_Of_Pay sounds like a fundamental quantity in the program; a good programmer would not give it a short identifier such as ``adrop''. In fact a coder might not even have the freedom to choose the name, since that name may be part of a data dictionary that came from the design stage. But disposable local variables that have an implementation-oriented meaning---such as loop counters, temporary pointers and the like---should be given nothing but short names. To do otherwise would ascribe to them a significance that they do not have. What's the point of calling something ``Loop_Counter'' instead of ``i''? Or ``Destination_Buffer_Pointer'' instead of ``dp''? It's just distracting. It can also quickly lead to code that is wider than 79 columns, and that is a Bad Thing (tm). Here is an example with short, cryptic variable names from a reference implementation of an encryption algorithm of mine. Notice that not all the identifiers are short; there is ``rhyme and reason'' behind the selection of which objects have short identifiers. void pha_encipher(pha_cblock *plain, pha_cblock *cipher, pha_schedule *sched) { pha_cblock_internal a, b; unsigned long (*piece)[2] = sched->piece; int r; make_internal_cblock(plain, &a); b[2] = a[0]; b[3] = a[1]; for (r = 0; r < ROUNDS; ) { a[0] = apply_sbox(0, (mult_combine(b[2], piece[r][0]))); a[1] = apply_sbox(1, (mult_combine(b[3], piece[r][1]))); rotate_left(a); a[2] = a[2] ^ a[0]; a[3] = a[3] ^ a[1]; r++; b[0] = apply_sbox(2, (mult_combine(a[2], piece[r][0]))); b[1] = apply_sbox(3, (mult_combine(a[3], piece[r][1]))); rotate_left(b); b[2] = b[2] ^ b[0]; b[3] = b[3] ^ b[1]; r++; } b[0] = a[2]; b[1] = a[3]; make_external_cblock(cipher, &b); } I can't think of a reasonable name to give to the two intermediate cipher blocks other than 'a' and 'b'. I could have called them 'L' and 'R', except that their roles exchange after every round. The code is confusing enough without being made lexically incomprehensible with long names. It's important that the array indices ``stand out'', which makes them easy to inspect for errors. I originally had longer names, but it was unmanageable. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` Kaz Kylheku @ 1997-05-08 0:00 ` Robert Dewar 1997-05-09 0:00 ` Kaz Kylheku 1997-05-12 0:00 ` W. Wesley Groleau (Wes) 1997-05-14 0:00 ` Nick Roberts 2 siblings, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-08 0:00 UTC (permalink / raw) Kaz said <<I can't think of a reasonable name to give to the two intermediate cipher blocks other than 'a' and 'b'>> Whenever you cannot think of a reasonable name to give to a variable, that is a priori suspicious, it suggests that the expression of the algorithm involving the variables is not as clear as it might be. Sure, short names are appropriate sometime, but you should always be able to give a very clear description of a variable. Essentially this desription is an invariant that describes the meaning of the value of the variable "Intermediate value" is not a very useful invariant! ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` Robert Dewar @ 1997-05-09 0:00 ` Kaz Kylheku 0 siblings, 0 replies; 120+ messages in thread From: Kaz Kylheku @ 1997-05-09 0:00 UTC (permalink / raw) In article <dewar.863148621@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Kaz said > ><<I can't think of a reasonable name to give to the two intermediate >cipher blocks other than 'a' and 'b'>> > >Whenever you cannot think of a reasonable name to give to a variable, that >is a priori suspicious, it suggests that the expression of the algorithm >involving the variables is not as clear as it might be. Sure, short names Of course not! This is encryption we are talking about. :) >are appropriate sometime, but you should always be able to give a very >clear description of a variable. Essentially this desription is an invariant >that describes the meaning of the value of the variable > >"Intermediate value" is not a very useful invariant! Hmm. I still can't come up with names. There isn't really an invariant that governs 'a' and 'b'; their contents get scrambled by the encryption rounds, according to the arbitrary S-boxes and other operations. The initial values are also meaningless, because they are just arbitrary bits being encrypted. So 'a' and 'b' they will have to stay. Note that other identifiers are quite meaningful. The identifier ``piece'' refers to scheduled portions of the key material. Likewise ``make_external_cblock'' is a clear reference to conversion between a more efficient internal representation to a more convenient (to the user) external representation. There was no problem in naming ``apply_sbox'' or ``mult_combine''. But ``a'' and ``b'' are just faceless victims that have stuff done to them. :) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert Dewar @ 1997-05-12 0:00 ` W. Wesley Groleau (Wes) 1997-05-12 0:00 ` John G. Volan 1997-05-14 0:00 ` Nick Roberts 2 siblings, 1 reply; 120+ messages in thread From: W. Wesley Groleau (Wes) @ 1997-05-12 0:00 UTC (permalink / raw) Kaz Kylheku wrote: > What's the point of calling something ``Loop_Counter'' instead of ``i''? A good Ada programmer will often choose something with some meaning rather than _either_ `Loop_Counter'' or ``i'' for Hue in Colors loop .... > I can't think of a reasonable name to give to the two intermediate > cipher blocks other than 'a' and 'b'. If there is no meaningful name possible then short meaningless names are better than long meaningless names. It appears that your example was this way. But in other examples, inability to think of a meaningful name comes from not thinking enough of a meaningful design. ---------------------------------------------------------------------- Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA Senior Software Engineer - AFATDS Tool-smith Wanna-be w w g r o l at p s e u l t 0 1 dot f w dot h a c dot c o m SPAM should be sent to I.want.one@mailbombs.for.idiots.org If you don't want to pay $500 (see 47 USC 227), don't send it here. ---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-12 0:00 ` W. Wesley Groleau (Wes) @ 1997-05-12 0:00 ` John G. Volan 0 siblings, 0 replies; 120+ messages in thread From: John G. Volan @ 1997-05-12 0:00 UTC (permalink / raw) W. Wesley Groleau (Wes) wrote: > > Kaz Kylheku wrote: > > What's the point of calling something ``Loop_Counter'' instead of ``i''? > > A good Ada programmer will often choose something with some meaning > rather > than _either_ `Loop_Counter'' or ``i'' > > for Hue in Colors loop .... Yes, this is certainly much better, but (to cross-reference another thread) this would be even better as any one of the following: for Next_Hue in Hue loop... -- Booch's style (once mine) for Hue in Hue_Type loop... -- Cohen's style (now mine) for Hue in Hues loop... or for Next_Color in Color loop... -- Booch's style (once mine) for Color in Color_Type loop... -- Cohen's style (now mine) for Color in Colors loop... ------------------------------------------------------------------------ Internet.Usenet.Put_Signature (Name => "John G. Volan", Home_Email => "johnvolan@sprintmail.com", Slogan => "Ada95: The World's *FIRST* International-Standard OOPL", Disclaimer => "These opinions were never defined, so using them " & "would be erroneous...or is that just nondeterministic now? :-) "); ------------------------------------------------------------------------ ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-08 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert Dewar 1997-05-12 0:00 ` W. Wesley Groleau (Wes) @ 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 1997-05-15 0:00 ` Kaz Kylheku 2 siblings, 2 replies; 120+ messages in thread From: Nick Roberts @ 1997-05-14 0:00 UTC (permalink / raw) Kaz Kylheku <kaz@vision.crest.nt.com> wrote in article <5ktldo$2pp@bcrkh13.bnr.ca> an example of the use of short identifiers in some C code. I think Kaz' example illustrates quite neatly that there are places where a short identifier is appropriate. Remember, the Ada 95 standard defines the constants 'Pi' and 'e' in Ada.Numerics, and these can hardly be cited as examples of long identifiers! And yet, they are highly appropriate, are they not? I am not impressed by programmers who get religious about these things. Having said that, I would caution against the use of single-letter identifiers where possible, for the extremely pragmatic reason that trying to do a search-and-replace on them (e.g. to change all occurrences of variable 'a' to 'x') a minefield. It's almost always easy to use two letters instead (e.g. 'na' and 'nb' instead of just 'a' and 'b'), and generally makes search-and-replace much less dangerous. If I could have a penny for every time I've fallen foul of that one ... ;-) Nick. (See - I have a short identifier) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-14 0:00 ` Nick Roberts @ 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Jeff Carter 1997-05-15 0:00 ` Kaz Kylheku 1 sibling, 1 reply; 120+ messages in thread From: Robert Dewar @ 1997-05-14 0:00 UTC (permalink / raw) Nick says <<Having said that, I would caution against the use of single-letter identifiers where possible, for the extremely pragmatic reason that trying to do a search-and-replace on them (e.g. to change all occurrences of variable 'a' to 'x') a minefield. It's almost always easy to use two letters instead (e.g. 'na' and 'nb' instead of just 'a' and 'b'), and generally makes search-and-replace much less dangerous. If I could have a penny for every time I've fallen foul of that one ... ;-)>> That last piece of advice of course is a reflection of decrepit tools. At the very least, you should have an editor that recognizes identifier words, rather than just blindly replaces characters, and ideally you should have a decent tool that knows about Ada references. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-14 0:00 ` Robert Dewar @ 1997-05-14 0:00 ` Jeff Carter [not found] ` <dewar.863632434@merv> 0 siblings, 1 reply; 120+ messages in thread From: Jeff Carter @ 1997-05-14 0:00 UTC (permalink / raw) Robert Dewar wrote: > > Nick says > > <<Having said that, I would caution against the use of single-letter > identifiers where possible, for the extremely pragmatic reason that trying > to do a search-and-replace on them (e.g. to change all occurrences of > variable 'a' to 'x') a minefield. It's almost always easy to use two > letters instead (e.g. 'na' and 'nb' instead of just 'a' and 'b'), and > generally makes search-and-replace much less dangerous. If I could have a > penny for every time I've fallen foul of that one ... ;-)>> > > That last piece of advice of course is a reflection of decrepit tools. At > the very least, you should have an editor that recognizes identifier words, > rather than just blindly replaces characters, and ideally you should have > a decent tool that knows about Ada references. This is true. However, having worked on a US$billion project on which the only tools were an Ada compiler (this was before 1995, so it was an Ada-83 compiler in today's parlance), UNIX, and vi (that's right, not even a source-level debugger), I view all claims that "this problem is solved by better tools" with a jaundiced eye. -- Jeff Carter PGP:1024/440FBE21 Auntie-spam reply to; try ( carter @ innocon . com ) "Now go away, or I shall taunt you a second time." Monty Python & the Holy Grail ^ permalink raw reply [flat|nested] 120+ messages in thread
[parent not found: <dewar.863632434@merv>]
* Re: Not intended for use in medical, [not found] ` <dewar.863632434@merv> @ 1997-05-15 0:00 ` Kaz Kylheku 1997-05-18 0:00 ` Robert Dewar 0 siblings, 1 reply; 120+ messages in thread From: Kaz Kylheku @ 1997-05-15 0:00 UTC (permalink / raw) In article <dewar.863632434@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: >Jeff Carter said > ><<This is true. However, having worked on a US$billion project on which >the only tools were an Ada compiler (this was before 1995, so it was an >Ada-83 compiler in today's parlance), UNIX, and vi (that's right, not >even a source-level debugger), I view all claims that "this problem is >solved by better tools" with a jaundiced eye.>> > >Someone chose these tools, and I would blame the chooser rather than the >tools. You certainly had better development tools than this avaiable >to you. Some of us wouldn't have it any other way. Vi is by far the best text mangler there is. At least the core concept behind vi. The implementation is dead---the freeware clones like Vim are far better and offer significant advancements over their SVR4 shadow. Then again, I'm a masochist. I'm typing on an amber-screen terminal that I got for $5 from some hacker years ago. The date on its ``motherboard'' is 1985. The high-resolution monitor connected to my machine is turned off. I hate its instant refresh rate. I like to see the optimized text redraws at 19200 baud (if the thing was a real WYSE rather than a Tandy clone, it would probably take the 38400). It sort of gives me a better sense of where I am in the text and where I'm going. Plus I like the color. Who needs 16.7 million colors, when you can shatter them all with that exquisitely perfect hue of amber? Ah, ever the incorrigible fanatic. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-15 0:00 ` Kaz Kylheku @ 1997-05-18 0:00 ` Robert Dewar 0 siblings, 0 replies; 120+ messages in thread From: Robert Dewar @ 1997-05-18 0:00 UTC (permalink / raw) Kaz said <<Some of us wouldn't have it any other way. Vi is by far the best text mangler there is. At least the core concept behind vi. The implementation is dead---the freeware clones like Vim are far better and offer significant advancements over their SVR4 shadow.>> PLEASE! Let's not have silly editor wars on CLA -- that would be tiresome even by the standards of some of the more dismal threads around here :-) ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar @ 1997-05-15 0:00 ` Kaz Kylheku 1 sibling, 0 replies; 120+ messages in thread From: Kaz Kylheku @ 1997-05-15 0:00 UTC (permalink / raw) In article <01bc5ff7$22677e60$LocalHost@xhv46.dial.pipex.com>, Nick Roberts <Nick.Roberts@dial.pipex.com> wrote: > > >Kaz Kylheku <kaz@vision.crest.nt.com> wrote in article ><5ktldo$2pp@bcrkh13.bnr.ca> an example of the use of short identifiers in >some C code. > >I think Kaz' example illustrates quite neatly that there are places where a >short identifier is appropriate. Remember, the Ada 95 standard defines the It's not like I started doing this yesterday, after all. And it's not like there aren't any long_identifier_names in the routine, like make_external_cblock and apply_sbox. I will grant you that cblock is a little cryptic, since it's short for cipherblock. I think I copied the contraction from Eric Young's LibDES interface, which defines the type des_cblock. >constants 'Pi' and 'e' in Ada.Numerics, and these can hardly be cited as >examples of long identifiers! And yet, they are highly appropriate, are >they not? I am not impressed by programmers who get religious about these >things. > >Having said that, I would caution against the use of single-letter >identifiers where possible, for the extremely pragmatic reason that trying >to do a search-and-replace on them (e.g. to change all occurrences of >variable 'a' to 'x') a minefield. It's almost always easy to use two It's not bad with decent regex syntax. In the vi compatible editor I use, matching x as an identifier would be done as \<x\>. Those little doodads that surround the x anchor the search to the beginning and end of a delimited word, respectively. To be safe, I'd search for it ``manually'', like this /\<x\>. Upon hitting the first occurence I'd edit it to 'a' by typing 'ra'. Then I'd just hit 'n' for the next search and '.' to repeat the edit. n.n.n.n.n.n. Really quick and surgical. Or I'd do it automatically, but restrict the range of code (subranges are useful safety features in editing too :)) I could rename identifiers all day just for the sheer pleasure of the vi. :) >generally makes search-and-replace much less dangerous. If I could have a >penny for every time I've fallen foul of that one ... ;-) ...you might save up for some ice cream, because good editors often come in freeware form these days! >Nick. >(See - I have a short identifier) It's a short nick, indeed. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-06 0:00 ` Robert A Duff 1997-05-07 0:00 ` Robert Dewar @ 1997-05-07 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert A Duff 1 sibling, 1 reply; 120+ messages in thread From: Kaz Kylheku @ 1997-05-07 0:00 UTC (permalink / raw) In article <E9rMuy.Hs0@world.std.com>, Robert A Duff <bobduff@world.std.com> wrote: >In article <5kmek2$9re@bcrkh13.bnr.ca>, >Kaz Kylheku <kaz@vision.crest.nt.com> wrote: >>>> Yes, legal, but horrible. A good reminder of why Ada does NOT have >>>> the ++ operator built in :-) >> >>By the way, the x++ is just another way of writing the assignment expression x >>+= 1, or x = x + 1 (the latter case evaluates x twice, of course). The real >>``evil'' perhaps is that in C an assignment is an expression rather than a >>statement, so that you can decorate a complex expression with assignments all >>over the place. > >I agree (except I'd remove "perhaps"). There's nothing wrong with >having short-hand notations like "++" and "+=". The language design >flaw in C is that assignments return something "useful", thus >encouraging side effects nested within expressions, like a[i++]. >I'm not against *all* kinds of side effects, but I'm against most of >them, including the one mentioned above. Wouldn't you agree that C++ amplifies this problem greatly by not only allowing assigments to return something, but also by allowing assignments to serve as l-values? And without proper sequencing at that. ^ permalink raw reply [flat|nested] 120+ messages in thread
* Re: Not intended for use in medical, 1997-05-07 0:00 ` Kaz Kylheku @ 1997-05-08 0:00 ` Robert A Duff 0 siblings, 0 replies; 120+ messages in thread From: Robert A Duff @ 1997-05-08 0:00 UTC (permalink / raw) In article <5kqg8d$95@bcrkh13.bnr.ca>, Kaz Kylheku <kaz@vision.crest.nt.com> wrote: >Wouldn't you agree that C++ amplifies this problem greatly by not only >allowing assigments to return something, but also by allowing assignments >to serve as l-values? And without proper sequencing at that. Yeah, from what you say, it sounds like it amplifies the problem. I don't know this part of C++ well enough to judge whether this is a bad language design decision on the whole. That is, I don't know why this change was made -- maybe there are other good aspects about it. - Bob ^ permalink raw reply [flat|nested] 120+ messages in thread
end of thread, other threads:[~1997-05-30 0:00 UTC | newest] Thread overview: 120+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1997-04-23 0:00 Not intended for use in medical, Robert C. Leif, Ph.D. 1997-04-24 0:00 ` J. Florio 1997-04-25 0:00 ` Ken Garlington 1997-04-25 0:00 ` Kevin Cline 1997-04-25 0:00 ` Robert Dewar 1997-04-28 0:00 ` John Apa 1997-04-28 0:00 ` John M. Mills 1997-04-30 0:00 ` Larry Kilgallen 1997-05-02 0:00 ` Nick Roberts 1997-04-28 0:00 ` Robert Dewar 1997-04-29 0:00 ` Kaz Kylheku 1997-04-30 0:00 ` John Apa [not found] ` <3367CE1E.5ED1@die_spammer.dasd.honeywell.com> 1997-05-01 0:00 ` Kaz Kylheku 1997-05-03 0:00 ` Simon Wright 1997-05-04 0:00 ` Richard Kenner 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Kaz Kylheku 1997-05-04 0:00 ` Robert Dewar 1997-05-04 0:00 ` Richard Kenner 1997-05-05 0:00 ` Kaz Kylheku 1997-05-06 0:00 ` Kaz Kylheku 1997-05-06 0:00 ` Robert A Duff 1997-05-07 0:00 ` Robert Dewar 1997-05-08 0:00 ` John G. Volan 1997-05-10 0:00 ` Robert Dewar 1997-05-10 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert A Duff 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` John G. Volan 1997-05-11 0:00 ` John G. Volan 1997-05-11 0:00 ` Robert Dewar 1997-05-12 0:00 ` John G. Volan 1997-05-12 0:00 ` Robert Dewar 1997-05-17 0:00 ` Robert I. Eachus [not found] ` <dewar.863877808@merv> 1997-05-17 0:00 ` Robert Dewar 1997-05-17 0:00 ` Jon S Anthony 1997-05-21 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Ben Brosgol 1997-05-20 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Jon S Anthony 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Robert I. Eachus 1997-05-25 0:00 ` Matthew Heaney 1997-05-28 0:00 ` Robert I. Eachus 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony 1997-05-28 0:00 ` Syntax for tagged record types (was Re David Kristola 1997-05-23 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Simon Wright 1997-05-21 0:00 ` Syntax for tagged record types and class types Mats Weber 1997-05-21 0:00 ` Matthew Heaney 1997-05-22 0:00 ` Mats Weber 1997-05-27 0:00 ` Tucker Taft 1997-05-30 0:00 ` Mats.Weber 1997-05-22 0:00 ` Samuel A. Mize 1997-05-22 0:00 ` Samuel A. Mize 1997-05-23 0:00 ` Mats Weber [not found] ` <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net> 1997-05-22 0:00 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Robert A Duff 1997-05-22 0:00 ` John G. Volan 1997-05-23 0:00 ` Matthew Heaney 1997-05-23 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Matthew Heaney 1997-05-25 0:00 ` Jon S Anthony 1997-05-25 0:00 ` Robert Dewar 1997-05-27 0:00 ` Ray Blaak 1997-05-23 0:00 ` John G. Volan 1997-05-24 0:00 ` Robert A Duff 1997-05-24 0:00 ` Matthew Heaney 1997-05-28 0:00 ` Robert I. Eachus 1997-05-25 0:00 ` Jon S Anthony 1997-05-23 0:00 ` Jon S Anthony 1997-05-12 0:00 ` Not intended for use in medical, John G. Volan 1997-05-12 0:00 ` Language Design Mistakes (was "not intended...") W. Wesley Groleau (Wes) 1997-05-13 0:00 ` Robert Dewar 1997-05-13 0:00 ` W. Wesley Groleau (Wes) 1997-05-13 0:00 ` Robert A Duff 1997-05-14 0:00 ` Robert Dewar 1997-05-08 0:00 ` Not intended for use in medical, Robert A Duff 1997-05-09 0:00 ` Robert I. Eachus 1997-05-11 0:00 ` Robert Dewar 1997-05-11 0:00 ` Matthew Heaney 1997-05-12 0:00 ` Robert Dewar 1997-05-12 0:00 ` Matthew Heaney 1997-05-13 0:00 ` Jon S Anthony 1997-05-13 0:00 ` Matthew Heaney 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 1997-05-15 0:00 ` W. Wesley Groleau (Wes) 1997-05-12 0:00 ` Robert I. Eachus 1997-05-13 0:00 ` Robert Dewar 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar [not found] ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com> 1997-05-16 0:00 ` Robert A Duff 1997-05-16 0:00 ` Robert I. Eachus 1997-05-18 0:00 ` Nick Roberts 1997-05-18 0:00 ` Matthew Heaney 1997-05-19 0:00 ` Robert I. Eachus 1997-05-19 0:00 ` Matthew Heaney 1997-05-20 0:00 ` Nick Roberts 1997-05-20 0:00 ` Matthew Heaney 1997-05-21 0:00 ` Dale Stanbrough 1997-05-19 0:00 ` Robert A Duff 1997-05-16 0:00 ` Robert Dewar 1997-05-08 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert Dewar 1997-05-09 0:00 ` Kaz Kylheku 1997-05-12 0:00 ` W. Wesley Groleau (Wes) 1997-05-12 0:00 ` John G. Volan 1997-05-14 0:00 ` Nick Roberts 1997-05-14 0:00 ` Robert Dewar 1997-05-14 0:00 ` Jeff Carter [not found] ` <dewar.863632434@merv> 1997-05-15 0:00 ` Kaz Kylheku 1997-05-18 0:00 ` Robert Dewar 1997-05-15 0:00 ` Kaz Kylheku 1997-05-07 0:00 ` Kaz Kylheku 1997-05-08 0:00 ` Robert A Duff
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox