2467c2467
< $param_map->{$param}[HTML::Template::LOOP::PARAM_SET] = [@{$value}];
---
> $param_map->{$param}[HTML::Template::LOOP::PARAM_SET] = $value;
2612c2612
< eval { $result .= $line->output($x, $options->{loop_context_vars}); };
---
> eval { $line->output($x, $options->{loop_context_vars},\$result); };
2885a2886,2888
> my $result;
> my $blank = "";
> $result = shift or $result = \$blank;
2906c2908
< $result .= $template->output;
---
> ${$result} .= $template->output;
2914c2916
< return $result;
---
> return ${$result};
####
package Tie::Array::SubIterator;
use base Tie::Array;
sub TIEARRAY {
my $class = shift;
my %in = @_;
$in{'length'} = -1 unless $in{'length'} && $in{'length'} =~ /^\d$/;
die "Expected coderef for next option" unless ref($in{'next'}) eq "CODE";
die "Expected coderef for determine_end option" unless !defined($in{'determine_end'}) or $in{'length'} < 0 or ref($in{'determine_end'}) eq "CODE";
$in{'determine_end'} = sub { return defined(+shift->{'last_result'}) ? 0:1; } if (!$in{'determine_end'} && $in{'length'} < 0);
$in{'last_counted'} = 0;
$in{'ended'} = 0;
my $self = bless \%in, $class;
eval { $self->{'last_result'} = $self->{'next'}->($self,0) if $self->{'length'} < 0; };
$self->{'ended'} = 1 if $@;
return $self;
}
sub FETCH {
my $self = shift;
return $self->{'next'}->($shift,@_) if ($self->{length} > -1);
my $last = $self->{'last_result'};
eval { $self->{'last_result'} = $self->{'next'}->($self,++$_[0]) unless $self->{'ended'}; };
$self->{'ended'} = 1 if $@;
return $last;
}
sub FETCHSIZE {
$self = shift;
return $self->{'length'} if $self->{'length'} > -1;
++$self->{'last_counted'} unless ($self->{'ended'}) || ($self->{'ended'} = $self->{determine_end}->($self));
$self->{'last_counted'};
}
sub DESTROY {
my $self = $_[0];
$self->{destroy}->(@_) if ref($self->{destroy}) eq "CODE";
}
1;
##
##
#!/usr/bin/perl -w
use strict;
use Tie::Array::SubIterator;
use HTML::Template;
use Devel::Size qw(total_size);
my @array= (1..10_000);
sub next {
my $self = shift;
return undef if $_[0] > $#array;
return { num => $array[$_[0]], added => $array[$_[0]]+10, subtracted => $array[$_[0]]-10 };
}
my @old_method;
push @old_method, { "num" => $_, "added" => ($_ + 10), subtracted => $_-10 } for (@array);
print "old: ", total_size(\@old_method),$/;
print "new: ", total_size(\@array),$/;
tie my @data, "DMN::TieArrayForeach", next=>\&next;
my $tmpl = q|
|;
my $template = HTML::Template->new(scalarref => \$tmpl);
$template->param(data => \@old_method,bob=>"outer area");
my $one = $template->output();
$template->param(data => \@data,bob=>"outer area");
my $two = $template->output();
print "identical$/" if $one eq $two;
##
##
old: 2145624
new: 240056
identical