in reply to Agile syntax (abuse?)
Thus what I'd want would rather be a set of especially named methods such as
so that
But... that's exactly what arrayref-overloading does. I believe you can base your matrix class entirely on that. You'd access a matrix object $m like this
The syntax is pure Perl. Your's is more compact and closer to conventional mathematical notation. In fact, I like it and will keep it in mind for future matrix work.@$m # entire matrix, your syntax: $m->() $m->[ 1] # second row, your syntax $m->( 1); $m->[ 1]->[ 0] # individual element, your syntax $m->( 1, 0);
Later you say:
...which is based, obviously, on blessed subrefs and also takes an Inside-Out approach: the object does contain something, namely a reference to itself, which also builds a closure, but is still used only like an index for property access.
Boo! That spoils most of the inside-out fun. Your objects rely on their body being a coderef, never mind how you access properties. Your class is hybrid to begin with and can't easily accomodate (inheritance-wise) a foereign class.
And it's not necessary either. Subref overloading is powerful enough to make your objects act as if their body were a coderef without it actually being one.
I have re-worked your class to be a true inside-out class without changing its interface or, I believe, its behavior. You may still prefer the more perlish style direct array overloading gives you and rewrite it that way.
package Matrix; use strict; use warnings; use Scalar::Util qw/refaddr/; use Data::Dumper; use base 'Exporter'; our @EXPORT='matrix'; use overload ( '""' => 'stringify', '*' => 'mult', '*=' => 'multby', '**' => 'pow', '&{}' => '_code', ); sub matrix { Matrix->new(@_) } sub mkaoa { [[ @_[0,1] ], [ @_[2,3] ]] } { my %entry; my %code; sub entry : lvalue { my $id=refaddr shift; @_==0 ? $entry{$id} : @_==1 ? $entry{$id}[ $_[0] ] : $entry{$id}[ $_[0] ][ $_[1] ]; } sub _code : lvalue { $code{ refaddr shift} } sub DESTROY { my $id = refaddr shift; delete $entry{ $id}; delete $code{ $id}; } } sub new { my $class = shift; my $self = bless( \ my $o, $class); $self->init(@_); } sub init { my $obj=shift; $obj->_code = sub : lvalue { $obj->entry(@_); }; $obj->() = mkaoa @_; $obj; } sub stringify { my $m = shift; "[[@{ $m->( 0) }] [@{ $m->( 1) }]]"; } sub _mult { my ($s,$o)=@_; my $code = $s->_code; $s->(0,0)*$o->(0,0) + $s->(0,1)*$o->(1,0), $s->(0,0)*$o->(0,1) + $s->(0,1)*$o->(1,1), $s->(1,0)*$o->(0,0) + $s->(1,1)*$o->(1,0), $s->(1,0)*$o->(0,1) + $s->(1,1)*$o->(1,1); } sub mult { my ($s,$o)=@_; matrix $s->_mult($o) } sub multby { my ($s,$o)=@_; $s->() = mkaoa $s->_mult($o); $s; } sub pow { my ($self, $n) = @_; my $out = matrix 1,0,0,1; if ( $n < 6 ) { $out->multby( $self) for 1 .. $n } else { my $pow = matrix map @$_, @{ $self->() }; # clone $self while ( $n ) { $out->multby( $pow) if $n & 1; $pow->multby( $pow); $n = int $n/2; } } $out; } 1; __END__
Update: Replaced the Matrix code. Essential change: ->init now does a full initialization instead of leaving part of the job to ->new. Inessential: Replaced ->pow with a more efficient implementation. Also added a stringification method
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Agile syntax (abuse?)
by blazar (Canon) on Apr 04, 2007 at 10:48 UTC | |
by Anno (Deacon) on Apr 04, 2007 at 18:29 UTC | |
by blazar (Canon) on Apr 04, 2007 at 19:41 UTC | |
by Anno (Deacon) on Apr 05, 2007 at 18:24 UTC |