sub average_over_time { # # $ages[x,0] = time of article arrival # $ages[x,1] = age of article; # articles are thrown out of the pipe if they've arrived more than $maxage # ago. # my (@ages,$sumages); my $maxage=shift @_; return sub { my $limit=time-$maxage; # Squeeze out events that have timed out while (($#ages>-1) && ($ages[0][0]<$limit)) { $sumages-=$ages[0][1]; shift @ages; } if (defined($_[0])) { push(@ages,[time,$_[0]]); $sumages+=$_[0]; } $sumages=0 if $#ages == -1; return ($#ages>-1)?int($sumages/($#ages+1)):0; } } That gives me the ability to say: my $mail5=average_over_time(300); my $mail60=average_over_time(3600); #### $db{"time-mail5"}=&$mail5($time); $db{"time-mail60"}=&$mail60($time);