comp.lang.ada
 help / color / mirror / Atom feed
From: henkc@cognos.uucp (Henk Cazemier)
Subject: Re: First Class Routines [Long again]
Date: 16 Mar 89 19:30:41 GMT	[thread overview]
Message-ID: <5580@vendicator.UUCP> (raw)
In-Reply-To: 118@eiffel.UUCP

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 <routine>,
which has an attribute <routineAddress> and <context>. <routineAddress>
is obtained by using a feature similar to 'eif_attr' and <context> is
any object that inherits from the class <RoutineClient>.
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 <zero or more generics> <optional return>

		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

      parent reply	other threads:[~1989-03-16 19:30 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <114@eiffel.UUCP>
     [not found] ` <112@eiffel.UUCP>
     [not found]   ` <1297@wasatch.UUCP>
1989-03-12  7:30     ` First Class Routines [Long again] Bertrand Meyer
1989-03-12 19:04       ` Pierre Jouvelot
1989-03-14  1:12       ` G. Ewing
1989-03-14 18:44       ` First Class Routines [Not long this time] Dave Berry
1989-03-16 19:30       ` Henk Cazemier [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox