|
The concepts of roles and actors performing those roles has given a
lot of inspiration to programming language designers. Nevertheless,
they are not really supported today. In gbeta, the very expressive
type combination gives some support in this direction, and below we'll
look at three variations of an example showing how something role-like
can be achieved.
Considered as realizations of the concepts of roles and actors in
concrete language design, a general problem with these approaches is
that a role cannot be retracted. Once you play a given role, it will
stay around as part of your personality the rest of your life!
Anyway, this might not be a problem in concrete cases. Otherwise
we'll have to think of something better. ;-)
Example 4
This example shows how a concept of role playing can be expressed
entirely at the static level. Both the actors and the roles are given
as patterns (i.e. descriptions of substance), and only the combined
patterns are instantiated. This approach of course sets the scene at
compile-time.
(* FILE aex4.gb *)
-- betaenv:descriptor --
(#
(* This shows how specialization of nested
* patterns ('role1' and 'role2') can be used
* to "fill in the roles" with properties which are
* declared elsewhere, namely the 'LaurenceOlivier'
* and 'Madonna' patterns. This is role playing
* at the static level, since both the roles and
* the actors are patterns, and the are combined
* as patterns, and then instances are created of
* the combined patterns.
*)
actor:
(# name:< string;
limps:< boolean;
deaf:< boolean;
speak: (# do '\n'+name+': '->stdio; INNER #);
answer: speak
(# do (if deaf then 'Er..?'->stdio else 'Yes, quite so.'->stdio if);
(if limps then ' .. Ouch, my leg!!'->stdio if)
#)
#);
play:
(# role1:< actor(# name::(# do 'Hamlet'->value #)#);
role2:< actor(# name::(# do 'Ophelia'->value #)#);
r1: @role1;
r2: @role2;
do r1.speak(# do 'Oh, I love You, '+r2.name+'!'->stdio #)
->r2.answer;
r2.speak
(# do r1.name+', are you still seeing that Leigh woman?'->stdio #)
->r1.answer
#);
LaurenceOlivier: actor(# deaf::(# do true->value #)#);
Madonna: actor(# limps::(# do true->value #)#);
myPlay: play(# role1::LaurenceOlivier; role2::Madonna #)
do
myPlay
#) |
Example 5
The next example is a slight variation of example 4. The only
difference is that the actors are considered as being an ensemble, and
this ensemble is then as a whole combined with the play
hamlet , in order to connect the actors and their roles.
(* FILE aex5.gb *)
-- betaenv:descriptor --
(#
(* This shows how specialization of nested
* patterns ('role1' and 'role2') can be used
* to "fill in the roles" with "actors" defined
* in an ensemble with a given basic structure.
* In this case we use the 'twoActors' setup
* which simply states that there are two actors,
* but there could be other constraints, e.g. a
* basic scheme of actions taking place, implemented
* as hooks (virtuals) which must then be filled in.
*
* The 'twoActors' setup is then specialized to an
* "implementation aspect," 'anEnsemble', and
* independently to an "activity aspect," the
* 'hamlet' play. Finally the two aspects are
* combined in the do-part, and executed
*)
actor:
(# realname:< string;
name:< string;
limps:< boolean;
deaf:< boolean;
speak: (# do '\n'+name+' ('+realname+')'+': '->stdio; INNER #);
answer: speak
(# do (if deaf then 'Er..?'->stdio else 'Yes, quite so.'->stdio if);
(if limps then ' .. Ouch, my leg!!'->stdio if)
#)
#);
twoActors:
(# role1:< actor;
role2:< actor;
r1: @role1; r2: @role2
do INNER
#);
anEnsemble: twoActors
(# role1::<
(# realname::(# do 'Laurence Olivier'->value #);
deaf::(# do true->value #)
#);
role2::<
(# realname::(# do 'Madonna'->value #);
limps::(# do true->value #)
#)
do INNER
#);
hamlet: twoActors
(# role1::< actor(# name::(# do 'Hamlet'->value #)#);
role2::< actor(# name::(# do 'Ophelia'->value #)#);
do r1.speak(# do 'Oh, I love You, '+r2.name+'!'->stdio #)
->r2.answer;
r2.speak
(# do r1.name+', are you still seeing that Leigh woman?'->stdio #)
->r1.answer
#)
do
anEnsemble & Hamlet
#) |
Example 6
Finally, perhaps the most useful realization of the concepts of role
and actor, where dynamic specialization is used to
enhance two existing objects with two roles, and then letting them
play the usual stuff:
(* FILE aex6.gb *)
-- betaenv:descriptor --
(#
(* In yet another variation on this theme, we have
* reached "the real thing," namely using dynamic
* specialization of objects to make already
* existing objects (not predestined to it) play
* the two roles.
*)
actor:
(# name:< string;
limps:< boolean;
deaf:< boolean;
speak: (# do '\n'+name+': '->stdio; INNER #);
answer: speak
(# do (if deaf then 'Er..?'->stdio else 'Yes, quite so.'->stdio if);
(if limps then ' .. Ouch, my leg!!'->stdio if)
#)
#);
play:
(# role1:< actor(# name::(# do 'Hamlet'->value #)#);
role2:< actor(# name::(# do 'Ophelia'->value #)#);
r1: ^actor;
r2: ^actor;
enter (r1[],r2[])
do (role1##,role2##)->(r1##,r2##);
r1.speak(# do 'Oh, I love You, '+r2.name+'!'->stdio #)
->r2.answer;
r2.speak
(# do r1.name+', are you still seeing that Leigh woman?'->stdio #)
->r1.answer
#);
LaurenceOlivier,Madonna: ^actor
do
&actor(# deaf::(# do true->value #)#)[]->LaurenceOlivier[];
&actor(# limps::(# do true->value #)#)[]->Madonna[];
(LaurenceOlivier[],Madonna[])->play
#) |
Having experienced the suspicions of Madonna i great detail, we'll
continue with dynamic control structures.
| |