package Qstruct::Array; use strict; use Carp; use Tie::Array; our @ISA = ('Tie::Array'); sub TIEARRAY { my $class = shift; my $obj = shift; return bless $obj, $class; } sub FETCH { my $self = shift; my $index = shift; return $self->{a}->($index); } sub FETCHSIZE { my $self = shift; return $self->{n}; } sub STORE { croak "unable to modify a read-only Qstruct array"; } package Qstruct::ArrayRef; use strict; use overload ## Make this behave like an array ref '@{}' => sub { $_[0]->{arr} }, ## This method is used by Test::More is_deeply() ## FIXME: if it doesn't match is_deeply() prints dumb 'Operation """": no method found' error 'eq' => sub { my ($self, $compare) = @_; my $arr = $self->{arr}; return '' if @$arr != @$compare; for my $i (0 .. (@$compare - 1)) { return '' if $arr->[$i] ne $compare->[$i]; } return 1; }, ; sub new { my ($class, $elems, $elem_accessor, $raw_accessor) = @_; my @arr; tie @arr, 'Qstruct::Array', { n => $elems, a => $elem_accessor, }; return bless { n => $elems, arr => \@arr, a => $elem_accessor, raw => $raw_accessor, }, $class; } sub raw { my $self = shift; die "array type doesn't support raw access" if !$self->{raw}; $self->{raw}->(exists $_[0] ? $_[0] : my $o); return $o if !exists $_[0]; } sub foreach { my $self = shift; for my $i (0 .. ($self->{n} - 1)) { $self->{a}->($i, my $o); $_[0]->($o); } } sub len { return $_[0]->{n}; } sub get { my $self = shift; $self->{a}->($_[0], exists $_[1] ? $_[1] : my $o); return $o if !exists $_[1]; } 1;