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.7 required=5.0 tests=BAYES_00,INVALID_DATE, MSGID_SHORT,REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Xref: utzoo comp.lang.eiffel:105 comp.lang.ada:2198 comp.lang.c++:2811 Path: utzoo!dciem!dretor!nrcaer!sce!cognos!henkc From: henkc@cognos.uucp (Henk Cazemier) Newsgroups: comp.lang.eiffel,comp.lang.ada,comp.lang.c++ Subject: Re: First Class Routines [Long again] Message-ID: <5580@vendicator.UUCP> Date: 16 Mar 89 19:30:41 GMT References: <114@eiffel.UUCP> <112@eiffel.UUCP> <1297@wasatch.UUCP> <118@eiffel.UUCP> Reply-To: henkc@cognos.UUCP (Henk Cazemier) Organization: Cognos Inc., Ottawa, Canada List-Id: In article <118@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes: > From <1297@wasatch.UUCP>, by gilad%cs.utah.edu@wasatch.UUCP >> Bertrand Meyer proposes a solution, using >> a combination of deferred classes and constrained genericity. >> The solution proposed is inadequate. It requires us to define >> a special class for every function of every type we might want to >> use over a list (or set, or whatever structure). > > class ACTIVE_SET [V -> VALTYPE] ... > > VALTYPE is a deferred class that simply includes the specification of >the repeatable operation. Specification, not implementation: contrary >to what Mr. Bracha wrote in the message extract reproduced above, >VALTYPE does not need to express what ``repeatable_operation'' is >(e.g. square root or cube computation), but simply to specify >its signature (types of its arguments and results), plus any semantic >properties, expressed through assertions. Specifying the signature is >required for static type checking. In class VALTYPE, repeatable_operation >is a deferred routine, that is to say a routine specified but not >implemented. > This approach leads to an environment where there will be a separate class for each different specification of the signature. Using this approach as a general solution generates a large number of classes, which only contain a single routine. I used this approach at one time and quickly discovered that there should be a better way to accomplish this functionality. I implemented a class called , which has an attribute and . is obtained by using a feature similar to 'eif_attr' and is any object that inherits from the class . Some of the features are: setToRoutineInObject (rname: String; obj: RoutineClient) setToRoutineInClass (rname: String; cname: String) callProcedure callOne (obj: RoutineClient) callProcedureFor (context: RoutineClient) The call* features use a routine similar to the 'eif_rout' feature. (The 'eif_attr' and 'eif_rout' features were published by Dr. Meyer about a week ago.) The disadvantage is that there is absolutely no compile time or run time checking, though the parameters passed on the 'call' features are enforced, there is no check that you use the right 'call' feature. This is a big disadvantage, but I think that the language can be extended such that routines are treated as first class objects. > One way to summarize this discussion is to say that I do not know of any >good way to reconcile the following three language traits: > > 1. Routine arguments (in the above sense, i.e. routine arguments to > routines). > 2. Static type checking. > 3. A language design that makes it possible to have separate > compilation of modules. > The use of routines as objects can be checked at compile time by using a syntax that the defines the signature. Maybe something like: Routine the feature 'execute' would do the actual call for an instance of this. Like: CLASS VeryComplicatedStructure EXPORTS processUntil FEATURE ..... processUntil (proc: Routine[T->Comparable, Integer]: Boolean) is local done : Boolean; rank : Integer; element: Comparable do FROM element := firstElement UNTIL element.void OR done LOOP done := proc.execute (element, rank); rank := rank + 1; element := element.next END end; END; -- VeryComplicatedStructure This allows you to make classes like: CLASS myApplication FEATURE theCollection: VeryComplicatedSturcture; ..... printSomeElements (element: Comparable; rank: Integer): Boolean is do -- print the elements contents and the rank.... howMany := howMany - 1; result := howMany < 0 end; processAllElements (element: Comparable; rank: Integer): Boolean is do -- print the elements contents and the rank.... result := FALSE end; howMany : Integer; ... printElements is do -- if want to print a little then do howMany := 10; theCollection.processUntil ([printSomeElements]); -- if want to print all do theCollection.processUntil ([processAllElements]); end; end; Classes may also contain attributes that are Routine objects, something like: theActionProc : Routine[T->Comparable, Real, Real]; Using this approach the compiler will be able to determine whether a routine is used properly. I look forward to seeing this construct supported by Eiffel in the not so distant future. -- Henk Cazemier P.O. Box 9707 Cognos Incorporated 3755 Riverside Dr. VOICE: (613) 738-1338 x5220 FAX: (613) 738-0002 Ottawa Ontario, CANADA K1G 3Z4 UUCP: decvax!utzoo!dciem!nrcaer!cognos!henkc