) (02/12/91)
Since Ada does not provide for procedural variables, how do you/your associates handle the need for having a procedure or a task perform different duties depending on run-time circumstances? One scenario would be to pass an enumeration value to the procedure and then to use "if-then-else-end if" or "case" statements to determine which procedure should be run. This approach will work; however, it seems inelegant. Does anyone one out there have a "nifty" solution or idea that they would be willing to share? Thanks, JOSE D.
howard@esosun.css.gov (Howard Turner) (02/12/91)
jduarte@ternes.ICS.UCI.EDU (J o s e D u a r t e ! ! !) writes:
Since Ada does not provide for procedural variables, how
do you/your associates handle the need for having a procedure or
a task perform different duties depending on run-time circumstances?
Two methods come to mind immediately. Since I am involved developing
an Ada/Xt and Ada/widget_set I've had to solve this "problem".
The two methods are
1) use tasks. The prototype code for this is included at the end
of this posting. This code has been compiled linked and run
under several different hardware/compiler combinations and has
always run correctly.
2) Call it from C.
howard
howard@esosun.css.gov
--------------------prototype code starts here
package subprogram_pointer is
type func_ptr is private;
procedure execute (the_obj : in func_ptr);
generic
type local_ptr is private;
proc_id : in out local_ptr;
with procedure user_specified;
package proc_ptr is
end proc_ptr;
private
type func;
type func_ptr is access func;
end subprogram_pointer;
--**************************
with text_io;
with unchecked_conversion;
package body Subprogram_Pointer is
task type func is
entry Handle;
end func;
task body func is
begin
loop
select
accept Handle do
text_io.put_line ("in the wrong task");
end Handle;
or
terminate;
end select;
end loop;
end func;
procedure execute (the_obj : in func_ptr) is
begin
the_obj.Handle;
exception
when others =>
text_io.put_line("exception raised trying to execute a func_ptr");
raise;
end execute;
package body proc_ptr is
task type Local is
entry Handle;
end Local;
type local_task_ptr is access Local;
local_task : local_task_ptr;
function to_func_ptr is new unchecked_conversion (
Source => local_task_ptr,
Target => Local_Ptr);
task body Local is
begin
loop
select
accept Handle do
text_io.put_line("in the Local task");
User_Specified;
end Handle;
or
terminate;
end select;
end loop;
end Local;
begin
local_task := new Local;
proc_id := to_func_ptr (local_task);
exception
when others =>
text_io.put_line ("error starting the function pointer task");
raise;
end proc_ptr;
end Subprogram_Pointer;
--***************************
with text_io;
procedure the_callback is
begin
text_io.put_line("it worked");
end the_callback;
--**************************
with the_callback;
with text_io;
with subprogram_pointer;
procedure Subprogram_Driver is
cb1 : subprogram_pointer.func_ptr;
package anypackage is new subprogram_pointer.proc_ptr
(proc_id => cb1, user_specified => the_callback,
local_ptr => subprogram_pointer.func_ptr);
begin
subprogram_pointer.execute(cb1);
exception
when others =>
text_io.put_line("exception caught in main routine, reraise");
raise;
end Subprogram_Driver;
mneerach@iiic.ethz.ch (Matthias Ulrich Neeracher) (02/12/91)
In article <662@esosun.UUCP>, howard@esosun.css.gov (Howard Turner) writes: <> jduarte@ternes.ICS.UCI.EDU (J o s e D u a r t e ! ! !) writes: <> <> Since Ada does not provide for procedural variables, how <> do you/your associates handle the need for having a procedure or <> a task perform different duties depending on run-time circumstances? >Two methods come to mind immediately. Since I am involved developing >an Ada/Xt and Ada/widget_set I've had to solve this "problem". > >The two methods are > >1) use tasks. The prototype code for this is included at the end > of this posting. This code has been compiled linked and run > under several different hardware/compiler combinations and has > always run correctly. > >2) Call it from C. Could anybody explain what the rationale for not including procedural variables in Ada is (I have heard it has been discussed and dismissed again in the past few years) ? The only reason against it that I have seen is that procedural variables might put an additional cost to exception handling. Can anybody give a better explanation ? Matthias -- Matthias Neeracher mneerach@iiic.ethz.ch "These days, though, you have to be pretty technical before you can even aspire to crudeness." -- William Gibson, _Johnny Mnemonic_
g_harrison@vger.nsu.edu ((George C. Harrison) Norfolk State University) (02/13/91)
In article <662@esosun.UUCP>, howard@esosun.css.gov (Howard Turner) writes: > jduarte@ternes.ICS.UCI.EDU (J o s e D u a r t e ! ! !) writes: > > Since Ada does not provide for procedural variables, how > do you/your associates handle the need for having a procedure or > a task perform different duties depending on run-time circumstances? > > Two methods come to mind immediately. Since I am involved developing > an Ada/Xt and Ada/widget_set I've had to solve this "problem". > > The two methods are > > 1) use tasks. The prototype code for this is included at the end > of this posting. This code has been compiled linked and run > under several different hardware/compiler combinations and has > always run correctly. > > 2) Call it from C. > [etc.] I am of the impression that one reason procedure parameters were NOT placed into the Ada standard is that generic subroutines can do the same trick: Pasqual: procedure DEMO ( procedure F ( X, Y : INTEGER; var R : REAL ); S : CHAR); might be Ada: generic with procedure F ( X, Y : in INTEGER; R : in out FLOAT ); procedure DEMO ( S : in CHARACTER ); ~~~~~~~~~~~~~~~:::::::::::: procedure DEMO ( S : in CHARACTER ) is ..... end DEMO; ~~~~~~~~~~~~~~~:::::::::::: with DEMO; procedure MAIN is ................. procedure QQQ ( LEG1, LEG2 : in INTEGER; REALSTUFF : in out FLOAT) is .... end QQQ; procedure MYDEMO is new procedure DEMO ( F => QQQ); use MYDEMO; ...... end MAIN; -- George C. Harrison -------------- || -- My opinions and observations -- ---|| Professor of Computer Science || -- Only. ------------------------- ---|| Norfolk State University, ---- || ----------- Pray for Peace ------- ---|| 2401 Corprew Avenue, Norfolk, Virginia 23504 ----------------------- ---|| INTERNET: g_harrison@vger.nsu.edu ---------------------------------
stt@inmet.inmet.com (02/15/91)
Re: procedural variables The Ada 9X Requirements document, dated December 1990, includes a Study Topic and a Requirement dealing with subprograms as variables/parameters. This indicates that there is now general consensus that such a capability should be in the upcoming revision of Ada. As for why there were left out originally, yes it was probably that generics provide partial support, and also I think there were some concerns about safety. For Ada 9X, we believe we will be able to provide both a safe and flexible capability for subprograms as variables/parameters. Stay tuned... S. Tucker Taft stt@inmet.inmet.com Ada 9X Mapping/Revision Team Intermetrics, Inc. Cambridge, MA 02138
sampson@cod.NOSC.MIL (Charles H. Sampson) (02/16/91)
In article <24590@neptune.inf.ethz.ch> mneerach@iiic.ethz.ch writes: > >Could anybody explain what the rationale for not including procedural >variables in Ada is (I have heard it has been discussed and dismissed again >in the past few years) ? I've been searching for some pertinent ancient documents, but without success, so I'm going to have to rely on memory. Probably everybody remem- bers that Ada is the result of an effort by the U. S. Department of Defense. This effort had a limited scope: to define a single computer language that could be used for all embedded computer applications within the DoD. (An embedded computer is one that is a part of a larger system, such as an air- craft or a smart torpedo.) This was a well executed project. It began with a survey of many of the groups withing the DoD, to determine what capabili- ties were required, followed by a set of successively refined requirements documents. As I remember it, one result of this survey was that there was no need at all for procedural variables (in DoD embedded computer applica- tions). I also remember that the first requirements document (called Straw- man; this is the one I can't find) explicitly stated that the language would not have such a capability. In the successors to Strawman the requirement was stated positively in terms of the current three formal parameter modes. Incidentally, at one stage of this process the capability that ulti- mately became exceptions was defined as a fourth formal parameter mode. Charlie
madmats@elcgl.epfl.ch (02/16/91)
In my opinion, procedure variables were not included in Ada because of the restrictions that must be placed upon them, making the feature non-ortho- gonal. Most languages that have procedure variables allow only top-level (i.e. declared as library units or immediately within library packages) procedures as their values. This is the case of Modula-2 for instance. The reason for this restriction is obvious: otherwiswe, a local procedure might be called in a situation where its context is not present, as in the following example written in PV-Ada (Ada with proc. variables): ... type Proc is procedure; -- parameterless X : Proc; procedure P is A : Integer; procedure Q is begin A := A + 1; end; begin X := Q; end P; ... P; X; -- this should be a call to P.Q, which makes no sense. Now one might argue that it is easy to check (at runtime) if X's context is present at the moment X is called, but this is not so true because a simple check that P is currently being called is not sufficient as different invocations of P may create different contexts for Q, for instance by declaring subtypes with non-static bounds. This issue of 'dangling subprograms' is treated in more detail in the context of an object-oriented extension to Ada in Norman Cohen's report "Ada subtypes as subclasses", which I recommend. For Ada-9X, I would much prefer an object-oriented extension than support for procedure variables, because this would greatly extend the expressive power of the language and would simultaneoulsy provide support for procedure variables for those who really want them: a procedure value would be an object with no data and only one method. To me, a procedure value not tied to an object does not make much sense. After all, the 'need' for procedure variables has only become serious since people have been trying to interface x-toolkits with Ada (callbacks), but does that mean that callbacks are the right way of doing it ? Mats Weber
jls@yoda.Rational.COM (Jim Showalter) (02/18/91)
>>Could anybody explain what the rationale for not including procedural >>variables in Ada is (I have heard it has been discussed and dismissed again >>in the past few years) ? They were deemed unsafe, because it is possible to get all fouled up with lifetime issues. Consider this example: procedure outer (...) is type some_procedure_type is ... foo : some_procedure_type; procedure middle (...) is procedure short_lifetime (...) is -- MATCHES some_procedure_type begin ... end short_lifetime; begin foo := short_lifetime; end middle; begin middle (...); foo; -- WHAT SHOULD HAPPEN HERE? end outer; Anyway, 9x looks like it will have these puppies. How they get around problems like the above I don't know--I suggest raising program_error whenever it occurs. -- ***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd ever be able to find a company (or, for that matter, very many people) with opinions like mine. -- "When I want your opinion, I'll beat it out of you."
edwards@rutabaga.cis.ohio-state.edu (stephen edwards) (02/20/91)
In article <1991Feb16.141232.1@elcgl.epfl.ch> madmats@elcgl.epfl.ch writes: >After all, the 'need' for procedure variables has only >become serious since people have been trying to interface x-toolkits >with Ada (callbacks), but does that mean that callbacks are the right >way of doing it ? This isn't quite correct. Ironically, procedure _variables_ (in Ada) aren't even needed for X callbacks, as virtually all Ada-to-C X interfaces illustrate. One only need pass an indirect reference to an Ada procedure on to the C code. For this purpose, there isn't need of Ada-manipulable procedure variables. (this would not be true when interfacing to an all Ada implementation of X, of course.) But this statement, and a few of the past articles on this thread which point out that generics can be used in place of many forms of procedure variables, misses what may be the heart of the 'need.' Remember "table- driven programming"? Maybe you learned it by a different name, like "data-driven computation", computing with "dispatch tables", or something else. But the point is that real, live procedure variables _can be placed in data structures_. These data structures can be manipulated in arbitrary ways, and the final result can be passed to something that is, at heart, an interpreter. Now, that final "interpreting" routine has programmable semantics. What actions it performs can be controlled simply by placing procedure variables pointing to new routines into the data structure. How much the semantics can be altered (and how easily) is determined by the actual structure of the "table", how it is manipulated, the interpretation strategy, etc. This is a fairly conventional, but very powerful technique. It allows one to completely separate the "driver"/interpreter/execution framework from the "action routines"/"evaluation functions/etc, and pushes the time at which the binding between these two distinct parts are made off until run-time. It's common in highly programmable/configurable software tools which load a configuration file when they are run--this file is basically a description of the interpreted data structure in some abstract form. Without procedure variables, you can't completely separate the driver from the action routines. This makes the software somewhat less flexible and also more difficult to maintain. A few posters have hinted at such "alternative" uses for procedure variables, but no one had quite come right out and said it (if they did and I missed it, I apologize for the redundancy). -- Steve Stephen Edwards U.S. mail: 372 Jones Tower e-mail : edwards@cis.ohio-state.edu 101 Curl Drive home phone: (614)-293-0842 Columbus, OH 43210
jls@yoda.Rational.COM (Jim Showalter) (02/21/91)
Agreed: table-driven programming requires subprogram variables to work smoothly. We encounter other cases where they would be quite useful. By the way, we implemented subprogram variables when we wrote our Ada-based X bindings. Works quite well, and only requires the body of one package to be rehosted on each platform. The rest is pure Ada. -- ***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd ever be able to find a company (or, for that matter, very many people) with opinions like mine. -- "When I want your opinion, I'll beat it out of you."