From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site ucbvax.BERKELEY.EDU Path: utzoo!watmath!clyde!burl!ulysses!ucbvax!UMich-MTS.MAILNET!Geoff_Mendal From: Geoff_Mendal@UMICH-MTS.MAILNET Newsgroups: net.lang.ada Subject: Re: Procedures as arguments Message-ID: <964133@UMich-MTS.Mailnet> Date: Tue, 22-Oct-85 19:02:24 EDT Article-I.D.: UMich-MT.964133 Posted: Tue Oct 22 19:02:24 1985 Date-Received: Fri, 25-Oct-85 02:17:36 EDT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The ARPA Internet List-Id: >This may seem a naive question, since at first look it seems impossible: >can I (in Ada) pass the name (address) of a procedure to another procedure >to be executed by that called procedure? My goal is to have a general >procedure that will call the supplied procedure until certain well-defined >conditions occur, then return to the original caller. It is trivial to do >in C, but I cannot find anything comparable in Ada. Thanks for any help. Perhaps a generic subprogram with a formal subprogram parameter will accomplish what you want. Consider the following simple example: generic with procedure Supplied_Procedure; procedure General_Procedure; . . . procedure General_Procedure is begin -- perhaps do something here Supplied_Procedure; -- perhaps do something here end General_Procedure; All you need to do is instantiate the General_Procedure with the name of a "supplied" procedure which you wish the General_Procedure to call. For example, the following instantiation of General_Procedure will cause "Hello" to be printed by a "supplied" procedure. with General_Procedure, Text_Io; procedure Main is procedure Print_Hello is begin Text_Io.Put_Line("Hello"); end Print_Hello; procedure My_General_Procedure is new General_Procedure(Print_Hello); begin My_General_Procedure; end Main; For simplicity, the above example assumes neither General_Procedure nor its formal subprogram parameter pass any parameters. Passing parameters can also be done, but the parameters of a generic formal subprogram must match those of the actual subprogram. Hence, one can only use the above method to "pass" subprograms that match the generic formal subprogram's parameter profile. If generics don't do what you want, there might be another way, using address clauses. I DO NOT ADVOCATE THIS METHOD. In fact, the ARM states that doing so makes a program erroneous [ARM 13.5(8)]. Address clauses need not even be implemented. With this in mind, consider the following: with system; procedure General_Procedure(Some_Procedure_Address : in System.Address) is procedure Supplied_Procedure; for Supplied_Procedure use at Some_Procedure_Address; begin -- perhaps do something here Supplied_Procedure; -- perhaps do something here end General_Procedure; . . . with General_Procedure, Text_Io; procedure Main is procedure Print_Hello is begin Text_Io.Put_Line("Hello"); end Print_Hello; begin General_Procedure(Print_Hello'Address); end Main; I doubt that this method would ever work in practice. I have yet to find an implementation that will even compile/execute this second (erroneous) method without blowing up (maybe that's an omen). Geoff Mendal, Stanford U.