DoubleLinkedListElement.pm: package DoubleLinkedListElement; use Hash::Util (lock_keys); use strict; sub new { my $self = {}; $self->{VALUE} = undef; $self->{NEXT} = undef; $self->{PREV} = undef; bless $self; lock_keys(%$self); return $self; } sub value { my $self = shift; if (@_) { $self->{VALUE} = shift; } return $self->{VALUE}; } sub next { my $self = shift; my $ret = $self->{NEXT}; if (@_) { $self->{NEXT} = shift; } return $ret; } sub prev { my $self = shift; my $ret = $self->{PREV}; if (@_) { $self->{PREV} = shift; } return $ret; } 1; DoubleLinkedList.pm: package DoubleLinkedList; use DoubleLinkedListElement; use Hash::Util (lock_keys); use strict; sub new { my $self = {}; $self->{FIRST} = undef; $self->{LAST} = undef; bless $self; lock_keys(%$self); return $self; } sub first { my $self = shift; return $self->{FIRST}; } sub last { my $self = shift; return $self->{LAST}; } sub append { my ($self, $value) = @_; my $element = new DoubleLinkedListElement(); $element->value($value); if ($self->last()) { $self->last()->next($element); $element->prev($self->last()); $self->{LAST} = $element; } else { $self->{FIRST} = $element; $self->{LAST} = $element; } } sub process_thru_forward { my ($self, $func, @param) = @_; for (my $this = $self->first(); $this; $this = $this->next()) { &$func($this, @param); } } sub process_thru_backward { my ($self, $func, @param) = @_; for (my $this = $self->last(); $this; $this = $this->prev()) { &$func($this, @param); } } 1; test.pl: use Data::Dumper; use DoubleLinkedList; use strict; my $dl_list = new DoubleLinkedList; foreach (1..10) { $dl_list->append($_); } $dl_list->process_thru_forward(\&plus_and_display, 10); $dl_list->process_thru_backward(\&plus_and_display, 10); sub plus_and_display { my ($this, $adj) = @_; print $this->value + $adj, "\n"; }