sommar@enea.se (Erland Sommarskog) (04/08/90)
Norman H. Cohen (NCOHEN@IBM.COM) writes: >Andre' Alguero asks about how to write a procedure to iterate over >a set of discrete elements, specifying the actions to be performed >at each iteration at the point at which the procedure is invoked. >... >One Ada solution is to nest a generic procedure inside a generic >package. The generic package is parameterized by the element type >of the set. This seems like the straight-forward and natural solution to do it. In fact I suspected that I had misunderstood the original question, since this design is not difficult to come up with. However, consider Mr. Cohen's proposal: > generic > type Element_Type is (<>); -- some discrete type > package Set_Package is > type Set_Type is private; > -- Operations like union, intersection declared here... > generic > with procedure Process_One_Element (Element: in Element_Type); > procedure Process_Each_Element (Set: in Set_Type); Some years ago I wrote a binary tree package with a similar concept. When I was to use the package I discovered one thing I had missed. There was no way to interrupt the iteration. One way is of course to rewrite the package so that Process_one_element should take a second parameter Continue : OUT boolean; The problem with this is that if the user in 90% of the time wants to iterate through the entire set, this second parameter just clutters up his code, and he may even forget to initiate it with interesting results, unless the compiler catches the error. So I went for the other solution and simply and the wrote invoking procedure as: DECLARE done : EXCEPTION; PROCEDURE Test_One_Element (E : IN My_Element_Subtype) is BEGIN -- some stuff IF Found THEN RAISE Done; END IF; END Test_One_Element; PROCEDURE Find_First_Element IS NEW My_Set_Package.Process_Each_Element (Process_One_Element => Test_One_Element); BEGIN Find_First_Element (S); EXCEPTION WHEN Done => NULL; END; Now, I wouldn't say that this is the use of exception as intended, but rather a confirmation those who claim that says that exception is a structured GOTO. Yet, if this is the rare case, this solution seem to be preferable to a second, rarely-used continue parameter. What is the general opinion on this? Any better ideas? -- Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se
louboutn@ccvax.ucd.ie (Sylvain Louboutin, University College Dublin, Ireland) (04/11/90)
In article <1151@enea.se>, sommar@enea.se (Erland Sommarskog) writes: > Norman H. Cohen (NCOHEN@IBM.COM) writes: >>Andre' Alguero asks about how to write a procedure to iterate over >>a set of discrete elements, specifying the actions to be performed >>at each iteration at the point at which the procedure is invoked. [...] > Some years ago I wrote a binary tree package with a similar concept. > When I was to use the package I discovered one thing I had missed. > There was no way to interrupt the iteration. One way is of course > to rewrite the package so that Process_one_element should take a > second parameter > Continue : OUT boolean; > The problem with this is that if the user in 90% of the time wants to > iterate through the entire set, this second parameter just clutters > up his code, and he may even forget to initiate it with interesting > results, unless the compiler catches the error. [Erland then proposes to use an exception to interrupt the iteration] Why don't you write the procedure like this: (note that the 'continue' paramter mode is IN OUT instead o OUT) generic with procedure Process_One_Element (Element: in Element_Type; Continue : IN OUT boolean); procedure Process_Each_Element (Set: in Set_Type); procedure Process_Each_Element (Set: in Set_Type) is Continue: boolean := TRUE; -- other declaration... begin -- some statements loop -- some statements Process_One_Element (Current_Element, Continue); exit when not Continue; -- some statements end loop; -- some statements... end Process_Each_Element; The user (i.e. the programmer of the procedure 'Process_One_Element') doesn't need to bother about the parameter continue (except that s/he has to include it in the header of the procedure, but there is no need to set a value to it in the procedure Process_Each_Element) if s/he wants to iterate through all the set... -- -- Sylvain R.Y. Louboutin fax: (+353-1) 69-72-62 -- Dept of Computer Science, University College, Dublin 4, -- Ireland -- -- LOUBOUTN@CCVAX.UCD.IE, S_LOUBOUTIN@CS.UCD.IE, SLOUBH91@IRLEARN.BITNET
tdhammer@wsuiar.uucp (04/11/90)
In article <1151@enea.se>, sommar@enea.se (Erland Sommarskog) writes: [stuff from Cohen deleted] > > Some years ago I wrote a binary tree package with a similar concept. > When I was to use the package I discovered one thing I had missed. > There was no way to interrupt the iteration. One way is of course > to rewrite the package so that Process_one_element should take a > second parameter > Continue : OUT boolean; > The problem with this is that if the user in 90% of the time wants to > iterate through the entire set, this second parameter just clutters > up his code, and he may even forget to initiate it with interesting > results, unless the compiler catches the error. [more stuff deleted - code example] > Now, I wouldn't say that this is the use of exception as intended, > but rather a confirmation those who claim that says that exception is > a structured GOTO. Yet, if this is the rare case, this solution seem > to be preferable to a second, rarely-used continue parameter. > > What is the general opinion on this? Any better ideas? > -- > Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se My first reaction was that it was not the intended use of the exception, and then saw that the author admits it. I would go on to disagree with the argument of using the exception as a structured goto. An exception is exactly that, something that is not expected to occur and if it does is probably an error. My initial implementation thought would be to write a boolean function with any side effects of processing one element and returning the value for Continue. This perhaps comes from my C coding experiences and probably is not good practice. Perhaps this is an argument for an extension to the optional parameters to include out parameters that may or may not appear in the procedure call? That would be an interesting implementation. Tim .D. ------------------------------------------------------------------------------- Tim .D. Hammer BITNET: TDHAMMER@TWSUVAX Teaching/Research Assistant UUCP: uunet!ncrlnk!ncrwic!wsucsa!hammer Computer Science Dept. INTERNET: tdhammer@wsuiar.wsu.ukans.edu Wichita State University TalkNET: (316)689-3156 Wichita, Ks. 67208-1595 package DISCLAIMER is type VIEWS is NO_ONE_ELSES ; subtype OPINIONS is bigoted VIEWS ; end package DISCLAIMER ; ------------------------------------------------------------------------------- "A little learning is a dangerous thing." Alexander Pope
madmats%elcgl.epfl.ch@VMA.CC.CMU.EDU (Mats Weber) (04/11/90)
>When I was to use the package I discovered one thing I had missed. >There was no way to interrupt the iteration. One way is of course >to rewrite the package so that Process_one_element should take a >second parameter > Continue : OUT boolean; Personally, I prefer to use exceptions in this case, because it is really an EXCEPTIONal case. But if the additonal boolean parameter is to be used, then it can be better to make it 'in out' instead of 'out' so that if the action procedure does not modify the parameter (or the programmer forgets to set it, which leads to erroneous programs), iteration continues by default. example: generic with procedure Action(X : in Item; Quit : in out Boolean); procedure Iterate is Do_Quit : Boolean := False; begin loop ... Action(X, Do_Quit); exit when Do_Quit; end loop; end; Mats Weber Swiss Federal Institute of Technology EPFL DI LGL 1015 Lausanne Switzerland E-mail : madmats@elcgl.epfl.ch phone : +41 21 693 52 92 fax : +41 21 693 39 09
kassover@jupiter.crd.ge.com (David Kassover) (04/14/90)
In article <120.26224a7e@wsuiar.uucp> tdhammer@wsuiar.uucp writes: ... > >Perhaps this is an argument for an extension to the optional parameters >to include out parameters that may or may not appear in the procedure >call? That would be an interesting implementation. Would that not require that the compiler *not* verify that the out parameter is the target of an assignment? An important check, no? Perhaps an optional in out parameter, where the parameter is guaranteed to have at least the default value would work acceptably. I, myself, see nothing wrong with specifying a routine that raises an exception (and specifying the name of that exception). Therefore one can write an exception handler to interpret the exception as is appropriate in the outer routine. For example: Several routines that I use can raise the exception FILE_NOT_FOUND. This does not mean to me that this is an error. In fact, the presence of the file, and the not-raising of FILE_NOT_FOUND may indicate that an error has occurred. This question of "misuse" of Ada exceptions begins to remind me of the jihad between the structured programming mullahs who maintain that loops must be exited only in one place, and the rest of us in the real world, who know better. "A foolish consistency is the hobgoblin of small minds" -with apologies to Emerson -- =================================================== David Kassover kassover@ra.crd.ge.com kassover@crd.ge.com
mfeldman@seas.gwu.edu (Mike Feldman) (04/14/90)
In article <6827@crdgw1.crd.ge.com> kassover@jupiter.crd.ge.com (David Kassover) writes: > >This question of "misuse" of Ada exceptions begins to remind me >of the jihad between the structured programming mullahs who >maintain that loops must be exited only in one place, and the >rest of us in the real world, who know better. > Whoa. First, let's not get back into using inflammatory language. I think there are _lots_ of equally valid points of view on exceptions. The group has calmed down and gotten back to technical stuff; I, for one, would appreciate our all restraining ourselves from words like "jihad" and "mullah." Now to the issue: there is a perfectly legitimate school of thought that holds that one important purpose of the exception-raising/handling structures in Ada is to improve readability, specifically by creating a clear visual distinction between "normal" processing and "abnormal" (unusual, unexpected, let's not play semantics games here) processing. Assume you belong to this school (I do, or I wouldn't bore you with this). You then face the question of drawing the line, if you can, separating the normal from the abnormal. Here is where science stops and art begins, and the line is not bright and crisp. So there is plenty of room to discuss, like polite adults, this essentially philosophical question. At the two extremes are the case of popping an empty stack (clearly, at least to me, an abnormal situation calling for an exception report) and the case of handling CONSTRAINT_ERROR when, given a DAYS_OF_WEEK enumeration, (MON, TUE, WED, THU, FRI, SAT, SUN), one finds tomorrow by taking the 'SUCC of today. If today is SUN, this will obviously raise CONSTRAINT_ERROR. Clearly, to me, handling CONSTRAINT_ERROR here is _not_ the thing to do, because MON indeed follows SUN once a week. The only thing that makes it "abnormal" is a language idiosyncracy under which wraparound enumerations aren't supported directly. While handling CONSTRAINT_ERROR here is obviously permitted, I hold that doing so dilutes the readability benefits provided by exceptions. Better to face the language idiosyncracy directly, writing if today = SUN then tomorrow := MON else tomorrow := DAY'SUCC(today); end if; I have heard it conjectured that the "extra" test in the IF statement will lead to that ol' bugaboo, inefficiency; I haven't yet seen it proved, therefore will assume negligible performance differences that can easily be traded away for increased human performance. (Let me know if you have good evidence to the contrary). OK, so much for my two extreme cases. I happen to think that Kassover's example is an easily justified intermediate case. Should we start a discussion thread about other such intermediate cases? I'd find it worthwhile unless and until it degenerates to name-calling. By the way - I don't know of any structured-programming "mullahs" these days. Use of new features always moves from the extremes to the middle, as our understanding of them matures. If a project wants to set a local coding standard - again for whatever readability improvement they think they are after - that says "one exit from a loop, one return from a subprogram", I think that is their privilege, and we don't have to flame them for it. I wouldn't set such a standard myself, but I think they have a valid viewpoint. I have seen such standards. In industry. Is this Kassover's "real world"? I have _lots_ of friends in the academic world; I don't think any of 'em are "mullahs." --------------------------------------------------------------------------- Prof. Michael Feldman Department of Electrical Engineering and Computer Science The George Washington University Washington, DC 20052 +1-202-994-5253 mfeldman@seas.gwu.edu ---------------------------------------------------------------------------
mfeldman@seas.gwu.edu (Mike Feldman) (05/01/90)
In article <7050@fy.sei.cmu.edu> rsd@sei.cmu.edu (Richard S D'Ippolito) writes: > >(*) Yes, you can define one as an ADT, and at least one inplementation of >Pascal has the first as successor to last, but this means the bar is now the >exception! Isn't it better to aviod philosophical arguments as to which is >fundamental, more useful, or prevalent, and define them both as natural >components? This is a nice idea. Does anyone know if there was an Ada9x suggestion to provide this? --------------------------------------------------------------------------- Prof. Michael Feldman Department of Electrical Engineering and Computer Science The George Washington University Washington, DC 20052 +1-202-994-5253 mfeldman@seas.gwu.edu ---------------------------------------------------------------------------