Delegation syntax

2002-10-10 Thread Ralph Mellor

Problem:

You want to use delegation rather than inheritance to
add some capabilities of one class or object to 
another class or object.

Solution: 

Use a PROXY block:

class MyClass {

PROXY {
attr $left_front_wheel is Wheel;
attr $right_front_wheel is Wheel;

when 'steer'{ $left_front_wheel, $right_front_wheel }
}
...
}

Discussion: 

A PROXY block is somewhat analogous to the PRE
block of a sub or method. A PROXY block has, or at
least appears to have, an object that represents the
method call as its topic. The object stringifies to the
name of the method. The whens' blocks are a list of
objects that are to receive the message instead of
the object represented by the enclosing class. (That
part could be done other ways; I had to pick a way,
and did so fairly arbitrarily.)

Generalizing, I can imagine a number of dispatch,
marshalling, etc. related blocks at the class definition
level.

Roughly speaking, my idea is to do Damian's Delegation
class dressed using new clothes that look like ones from
the Apos that have come out since he wrote the module
at http://tinyurl.com/1qsk. A longer example follows. (I've
futzed a few things where I didn't understand Damian's
code or I'm not sure of a perl 6 thing.):

class MyClass {

PROXY {
attr $left_front_wheel is Wheel;
attr $right_front_wheel is Wheel;
attr $left_rear_wheel is Wheel;
attr $right_rear_wheel is Wheel;
attr FlyWheel $flywheel .= new;
attr MP3::Player $mp3 .= new;

when 'steer'{ $left_front_wheel, $right_front_wheel }
when 'drive'{ 'rotate_clockwise' => $left_rear_wheel,
  'rotate_anticlockwise' => $right_rear_wheel }
when 'power'{ 'brake' => $flywheel }
when 'brake'{ / .*_wheel / }
when 'halt' { 'brake' => SELF }
when /^MP_(.+)/ { sub { $1 } => $mp3 }
when 'debug'{ 'dump' => ATTRS } 
}
...
}

--
ralph



Re: Delegation syntax

2002-10-11 Thread Ralph Mellor

> [proposal for delegation syntax, drawing from Class::Delegation]
>
> If something is part of the method interface, it ought to be declared
> as a method.
>
> method steer is really(Wheel) is also(???) { .profit!!! }

That's tidy, and is sorta on the lines of my own initial thoughts.

But afaict this approach only works for a literal method-by-
method setup of delegation.

In Class::Delegation, Damian notes that his delegation
mechanisms can be specified for: 
a single method 
a set of nominated methods collectively 
any as-yet-undelegated methods 
all methods, delegated or not. 

and his examples included regexes and other dynamic
means of selecting the methods to which some specific
delegating rule or set of rules applied.

There are other factors that led me to the notion of using
one or more class level PROXY blocks, but the above is
probably the most compelling one.

Perhaps all this is too much power for the core. Or maybe
there's a need for a more general mechanism for selecting
and acting on (eg setting properties on) sets of class slots.

--
ralph



Dynamic scoping

2002-11-23 Thread Ralph Mellor
First, I'd like to confirm I've understood
C and C right:

1. C dynamically scopes changes to a
   variable's value to the enclosing block.
   It does not dynamically scope the name.
   The variable can obviously be a global.
   It can also make sense if it is lexical.
   Is the latter currently allowed?

2. C is a conditional C; it only
   restores a variable's value if, on exit
   from the enclosing block, the block is
   somehow considered to have "failed". It
   can be applied to a global or lexical.

The above two features are basically sugar
for what would otherwise be achieved with
paired FIRST/LAST/UNDO blocks.

Both must be applied to an existing variable.

Next, I want to do a better job of stating
a problem I wonder about:

Consider "environmental" values such as
"screen sizes, graphics contexts, file
handles, environment variables, and
foreign interface environment handles." [1]

Consider a sub One that is going to call
a 10 deep stack of subs such that sub Ten
needs to access one of these environmental
values. How do you pass the data?

A. Globals. Bad. Disastrous in threads.

B. Passed as args to all intervening subs.
   Verbose. Sometimes incredibly verbose.

C. Aggregate info into objects. But then
   you still have to do either 1 or 2 above
   with the object references. And it's a
   shame to be forced to the object paradigm
   unnecessarily.

D. Use $CALLERS::. Relatively succinct, but
   definitely error-prone and ugly.

Given what I understand of Perl 6 syntax,
Parrot, and Perl philosophy, I believe P6
should, and can fairly easily, provide a
good solution to the problem outlined above.

Does anyone agree the problem I've outlined
is inadequately addressed by $CALLERS::?

In previous emails I've suggested:

1. The notion of something like attaching
   a C property on variables, and
   picking appropriate defaults for its
   args (not/ro/rw), to allow the writer
   of a sub to easily strictly limit what
   a called sub can access.

2. The notion of args that are explicitly
   defined in a sub's sig but implicitly
   passed. This kills most of the verbosity
   of B above, while, in combination with
   the previous point, being otherwise just
   as safe as passing args explicitly all
   the way down the call stack.

[1]
http://tinyurl.com/2yhl

--
ralph



how to code a lazy pipeline?

2002-12-11 Thread Ralph Mellor
How would one most nicely code what I'll call
a lazy pipeline, such that the first result
from the final element of the pipeline can
appear as soon as the first result has been
processed from the intervening elements?

--
ralph



A6, parameters

2003-03-19 Thread Ralph Mellor
If one deploys a sub with optional-positional parameters,
one can't add a required parameter later without breaking
any existing calls that make use of any o-p parameters.
Right?

A6: "An rw parameter may only default to a valid lvalue. If
you find yourself wanting it to default to an ordinary value
because it's undefined, perhaps you really want //= instead:"

Wouldn't it make sense to allow //= in the sig and have it dwim?

A6: "All unbound named arguments are bound to elements of
the slurpy hash, if one was declared.  If no slurpy hash is
declared, an exception is thrown (although some standard
methods, like BUILD, will provide an implicitly declared
slurpy hash--known as %_ by analogy to @_--to handle surplus
named arguments)."

What about there always being an implied %_ and @_, but if
either get entries, perl generates a warning (unless it's
one of the methods like BUILD)?

A6: "It's also possible to transition directly from positional
arguments to the variadic list if optional positional
arguments have been completely specified."

Or if one uses pipes, right?

--
ralph