Skip to content

Commit

Permalink
Add "emits" and "observes" attribute declarations.
Browse files Browse the repository at this point in the history
"emits" is a shortcut for Reflex::Trait::EmitsOnChange.  "observes" is
a shortcut for Reflex::Trait::Observed.  Names and locations may change.
  • Loading branch information
rcaputo committed Sep 7, 2010
1 parent 134c7e0 commit 6eae87c
Show file tree
Hide file tree
Showing 23 changed files with 164 additions and 135 deletions.
18 changes: 1 addition & 17 deletions TODO
@@ -1,17 +1 @@
Current hot, outstanding TODOs:

---

Coderef callbacks require $self of the object calling them.
Otherwise, how do they invoke methods on that object?
I've done a half-baked implementation, but it needs:

Testing.
Examples and such modified.
Document modifications.
Release Reflex 0.080 since it's a big leap.
Alert people that the world has changed slightly.

---

For a larger, longer-term list of todos, please see docs/TODO.otl.
A complete list of TODOs is in docs/TODO.otl.
2 changes: 1 addition & 1 deletion dist.ini
@@ -1,5 +1,5 @@
name = Reflex
version = 0.072
version = 0.080
author = Rocco Caputo <rcaputo@cpan.org>
license = Perl_5
copyright_holder = Rocco Caputo
Expand Down
5 changes: 2 additions & 3 deletions eg/eg-05-composition.pl
Expand Up @@ -13,16 +13,15 @@
use Moose;
extends 'Reflex::Base';
use Reflex::UdpPeer;
use Reflex::Trait::Observed qw(observes);

has port => (
isa => 'Int',
is => 'ro',
);

has peer => (
observes peer => (
isa => 'Maybe[Reflex::UdpPeer]',
is => 'rw',
traits => ['Reflex::Trait::Observed'],
setup => sub {
my $self = shift;
Reflex::UdpPeer->new(
Expand Down
4 changes: 1 addition & 3 deletions eg/eg-08-observer-trait.pl
Expand Up @@ -14,10 +14,8 @@
use Reflex::POE::Wheel::Run;
use Reflex::Trait::Observed;

has child => (
traits => ['Reflex::Trait::Observed'],
observes child => (
isa => 'Maybe[Reflex::POE::Wheel::Run]',
is => 'rw',
);

sub BUILD {
Expand Down
23 changes: 5 additions & 18 deletions eg/eg-09-emitter-trait.pl
Expand Up @@ -11,21 +11,11 @@
use Moose;
extends 'Reflex::Base';
use Reflex::Interval;
use Reflex::Trait::Observed;
use Reflex::Trait::EmitsOnChange;
use Reflex::Trait::Observed;

has count => (
traits => ['Reflex::Trait::EmitsOnChange'],
isa => 'Int',
is => 'rw',
default => 0,
);

has ticker => (
traits => ['Reflex::Trait::Observed'],
isa => 'Maybe[Reflex::Interval]',
is => 'rw',
);
emits count => ( isa => 'Int', default => 0 );
observes ticker => ( isa => 'Maybe[Reflex::Interval]' );

sub BUILD {
my $self = shift;
Expand All @@ -48,12 +38,9 @@
package Watcher;
use Moose;
extends 'Reflex::Base';
use Reflex::Trait::Observed;

has counter => (
traits => ['Reflex::Trait::Observed'],
isa => 'Counter',
is => 'rw',
);
observes counter => ( isa => 'Counter' );

sub BUILD {
my $self = shift;
Expand Down
30 changes: 12 additions & 18 deletions eg/eg-10-setup.pl
Expand Up @@ -4,29 +4,24 @@
use strict;
use lib qw(../lib);

# Exercise the new "setup" option for EmitsOnChange and Observed
# traits.
# Exercise the new "setup" option for emitters and observers.

{
package Counter;
use Moose;
extends 'Reflex::Base';
use Reflex::Interval;
use Reflex::Trait::Observed;
use Reflex::Trait::EmitsOnChange;
use Reflex::Trait::Observed;

has count => (
traits => ['Reflex::Trait::EmitsOnChange'],
isa => 'Int',
is => 'rw',
default => 0,
emits count => (
isa => 'Int',
default => 0,
);

has ticker => (
traits => ['Reflex::Trait::Observed'],
isa => 'Reflex::Interval',
is => 'rw',
setup => sub {
observes ticker => (
isa => 'Reflex::Interval',
setup => sub {
Reflex::Interval->new( interval => 0.1, auto_repeat => 1 )
},
);
Expand All @@ -41,12 +36,11 @@
package Watcher;
use Moose;
extends 'Reflex::Base';
use Reflex::Trait::Observed;

has counter => (
traits => ['Reflex::Trait::Observed'],
isa => 'Counter|Undef',
is => 'rw',
setup => sub { Counter->new() },
observes counter => (
isa => 'Counter|Undef',
setup => sub { Counter->new() },
);

sub on_counter_count {
Expand Down
10 changes: 4 additions & 6 deletions eg/eg-13-irc-bot.pl
Expand Up @@ -12,8 +12,8 @@
package Bot;
use Moose;
extends 'Reflex::Base';
use Reflex::Trait::Observed;
use Reflex::POE::Session;
use Reflex::Trait::Observed;

use POE qw(Component::IRC);

Expand All @@ -22,11 +22,9 @@
is => 'rw',
);

has poco_watcher => (
isa => 'Reflex::POE::Session',
is => 'rw',
traits => ['Reflex::Trait::Observed'],
role => 'poco',
observes poco_watcher => (
isa => 'Reflex::POE::Session',
role => 'poco',
);

sub BUILD {
Expand Down
9 changes: 4 additions & 5 deletions eg/eg-14-synopsis.pl
Expand Up @@ -9,12 +9,11 @@
use Moose;
extends 'Reflex::Base';
use Reflex::Interval;
use Reflex::Trait::Observed;

has ticker => (
isa => 'Reflex::Interval',
is => 'rw',
setup => { interval => 1, auto_repeat => 1 },
traits => [ 'Reflex::Trait::Observed' ],
observes ticker => (
isa => 'Reflex::Interval',
setup => { interval => 1, auto_repeat => 1 },
);

sub on_ticker_tick {
Expand Down
5 changes: 2 additions & 3 deletions eg/eg-37-ping-pong.pl
Expand Up @@ -18,12 +18,11 @@
package Pinger;
use Moose;
extends 'Reflex::Base';
use Reflex::Trait::Observed;

has echoer => (
is => 'ro',
observes echoer => (
isa => 'Echoer',
default => sub { Echoer->new() },
traits => ['Reflex::Trait::Observed'],
);

sub BUILD {
Expand Down
1 change: 1 addition & 0 deletions eg/eg-42-reflex-in-poe.pl
Expand Up @@ -2,6 +2,7 @@

use warnings;
use strict;
use lib qw(../lib);

my $rot13_server_port = 12345;

Expand Down
20 changes: 11 additions & 9 deletions lib/Reflex.pm
Expand Up @@ -53,12 +53,11 @@ Reflex - Class library for flexible, reactive programs.
use Moose;
extends 'Reflex::Base';
use Reflex::Interval;
use Reflex::Trait::Observed;
has ticker => (
observes ticker => (
isa => 'Reflex::Interval',
is => 'rw',
setup => { interval => 1, auto_repeat => 1 },
traits => [ 'Reflex::Trait::Observed' ],
);
sub on_ticker_tick {
Expand Down Expand Up @@ -103,19 +102,18 @@ warnings, strict, and base instead. Reflex::Base provides emit().
}
The next object uses Echoer. It creates an Echoer and pings it to get
started. It also reacts to "pong" events by pinging the Echoer again.
Reflex::Trait::Observed implicitly watches the object in echoer(),
mapping its "pong" event to the on_echoer_pong() method.
started. It also reacts to "pong" events by pinging the Echoer again.
Reflex::Trait::Observed (via its exported observes() declarative
syntax) implicitly watches the object in echoer(), mapping its "pong"
event to the on_echoer_pong() method.
package Pinger;
use Moose;
extends 'Reflex::Base';
has echoer => (
is => 'ro',
observes echoer => (
isa => 'Echoer',
default => sub { Echoer->new() },
traits => ['Reflex::Trait::Observed'],
);
sub BUILD {
Expand Down Expand Up @@ -339,6 +337,10 @@ observable object attributes.
=back
Reflex::Trait::EmitsOnchange exports a declarative emits() function
that simplifies use of this trait. Likewise, Reflex::Trait::Observed
exports observes() to simplify its use.
=head1 ASSISTANCE
Thank you for volunteering to assist with this project. You can find
Expand Down
5 changes: 2 additions & 3 deletions lib/Reflex/Callback.pm
@@ -1,12 +1,11 @@
package Reflex::Callback;

use Moose;
use Reflex::Base;

# It's a class if it's a Str.
has object => (
is => 'ro',
isa => 'Object|Str', # TODO - Reflex::Base|Str
is => 'rw',
isa => 'Object|Str',
weak_ref => 1,
);

Expand Down
21 changes: 14 additions & 7 deletions lib/Reflex/Callbacks.pm
Expand Up @@ -44,11 +44,12 @@ has callback_map => (

coerce 'Reflex::Callback'
=> from 'CodeRef'
=> via { Reflex::Callback::CodeRef->new( code_ref => $_ ) };
=> via { die; Reflex::Callback::CodeRef->new( code_ref => $_ ) };

coerce 'Reflex::Callback'
=> from 'Str'
=> via {
die;
Reflex::Callback::Method->new(
method_name => $_,
)
Expand All @@ -57,6 +58,7 @@ coerce 'Reflex::Callback'
coerce 'Reflex::Callback'
=> from 'ArrayRef'
=> via {
die;
Reflex::Callback::Method->new(
object => $_->[0],
method_name => $_->[1],
Expand Down Expand Up @@ -133,7 +135,7 @@ sub cb_coderef (&) {
}

sub gather_cb {
my ($arg, $match) = @_;
my ($owner, $arg, $match) = @_;
$match = qr/^on_/ unless defined $match;

my %return;
Expand All @@ -149,6 +151,7 @@ sub gather_cb {
}

if ($callback->isa('Reflex::Callback')) {
$callback->object($owner) unless $callback->object();
$return{$_} = $callback;
next;
}
Expand All @@ -159,7 +162,10 @@ sub gather_cb {
# Unblessed callback types must be coerced.

if (ref($callback) eq "CODE") {
$return{$_} = Reflex::Callback::CodeRef->new(code_ref => $callback);
$return{$_} = Reflex::Callback::CodeRef->new(
object => $owner,
code_ref => $callback,
);
next;
}

Expand Down Expand Up @@ -392,9 +398,10 @@ The gather_cb() function extracts callbacks from an object's
constructor parameters and encapsulates them in a Reflex::Callbacks
object.
gather_cb() takes two parameters: A hash reference containing a
constructor's named parameters, and an optional regular expression to
match callback parameter names. By default, gather_cb() will collect
gather_cb() takes three parameters: The object that will own the
callbacks, a hash reference containing a constructor's named
parameters, and an optional regular expression to match callback
parameter names. By default, gather_cb() will collect
parameters matching C</^on_/>.
package ThingWithCallbacks;
Expand All @@ -406,7 +413,7 @@ parameters matching C</^on_/>.
sub BUILD {
my ($self, $arg) = @_;
$self->cb(gather_cb($arg));
$self->cb(gather_cb($self, $arg));
}
sub run {
Expand Down
5 changes: 2 additions & 3 deletions lib/Reflex/Client.pm
Expand Up @@ -10,17 +10,16 @@ use Reflex::Stream;

extends 'Reflex::Connector';
with 'Reflex::Role::Collectible';
use Reflex::Trait::Observed;

has protocol => (
is => 'rw',
isa => 'Str',
default => 'Reflex::Stream',
);

has connection => (
is => 'rw',
observes connection => (
isa => 'Maybe[Reflex::Stream]',
traits => ['Reflex::Trait::Observed'],
# Maps $self->put() to $self->connection()->put().
# TODO - Would be nice to have something like this for outbout
# events. See on_connection_data() later in this module for more.
Expand Down
8 changes: 3 additions & 5 deletions lib/Reflex/PID.pm
Expand Up @@ -40,11 +40,9 @@ Reflex::PID - Observe the exit of a subprocess by its SIGCHLD signal.
use Reflex::PID;
has pid_watcher => (
isa => 'Reflex::PID|Undef',
is => 'rw',
traits => ['Reflex::Trait::Observed'],
role => 'process',
observes pid_watcher => (
isa => 'Reflex::PID|Undef',
role => 'process',
);
sub some_method {
Expand Down

0 comments on commit 6eae87c

Please sign in to comment.