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
prev 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