P e r l d o c B r o w s e r
●
5 . 0 0 5 _ 0 3
L a t e s t
5 . 4 0 . 0
5 . 3 8 . 2
5 . 3 8 . 1
5 . 3 8 . 0
5 . 3 6 . 3
5 . 3 6 . 2
5 . 3 6 . 1
5 . 3 6 . 0
5 . 3 4 . 3
5 . 3 4 . 2
5 . 3 4 . 1
5 . 3 4 . 0
5 . 3 2 . 1
5 . 3 2 . 0
5 . 3 0 . 3
5 . 3 0 . 2
5 . 3 0 . 1
5 . 3 0 . 0
5 . 2 8 . 3
5 . 2 8 . 2
5 . 2 8 . 1
5 . 2 8 . 0
5 . 2 6 . 3
5 . 2 6 . 2
5 . 2 6 . 1
5 . 2 6 . 0
5 . 2 4 . 4
5 . 2 4 . 3
5 . 2 4 . 2
5 . 2 4 . 1
5 . 2 4 . 0
5 . 2 2 . 4
5 . 2 2 . 3
5 . 2 2 . 2
5 . 2 2 . 1
5 . 2 2 . 0
5 . 2 0 . 3
5 . 2 0 . 2
5 . 2 0 . 1
5 . 2 0 . 0
5 . 1 8 . 4
5 . 1 8 . 3
5 . 1 8 . 2
5 . 1 8 . 1
5 . 1 8 . 0
5 . 1 6 . 3
5 . 1 6 . 2
5 . 1 6 . 1
5 . 1 6 . 0
5 . 1 4 . 4
5 . 1 4 . 3
5 . 1 4 . 2
5 . 1 4 . 1
5 . 1 4 . 0
5 . 1 2 . 5
5 . 1 2 . 4
5 . 1 2 . 3
5 . 1 2 . 2
5 . 1 2 . 1
5 . 1 2 . 0
5 . 1 0 . 1
5 . 1 0 . 0
5 . 8 . 9
5 . 8 . 8
5 . 8 . 7
5 . 8 . 6
5 . 8 . 5
5 . 8 . 4
5 . 8 . 3
5 . 8 . 2
5 . 8 . 1
5 . 8 . 0
5 . 6 . 2
5 . 6 . 1
5 . 6 . 0
5 . 0 0 5 _ 0 4
5 . 0 0 5 _ 0 3
5 . 0 0 5 _ 0 2
5 . 0 0 5 _ 0 1
5 . 0 0 5
●
D e v
b l e a d
5 . 4 1 . 2
5 . 4 1 . 1
5 . 4 0 . 0 - R C 2
5 . 4 0 . 0 - R C 1
5 . 3 9 . 1 0
5 . 3 9 . 9
5 . 3 9 . 8
5 . 3 9 . 6
5 . 3 9 . 5
5 . 3 9 . 4
5 . 3 9 . 3
5 . 3 9 . 2
5 . 3 9 . 1
5 . 3 7 . 1 1
5 . 3 7 . 1 0
5 . 3 7 . 9
5 . 3 7 . 8
5 . 3 7 . 7
5 . 3 7 . 6
5 . 3 7 . 5
5 . 3 7 . 4
5 . 3 7 . 3
5 . 3 7 . 2
5 . 3 7 . 1
5 . 3 7 . 0
●
D o c u m e n t a t i o n
P e r l
I n t r o
T u t o r i a l s
F A Q s
R e f e r e n c e
O p e r a t o r s
F u n c t i o n s
V a r i a b l e s
M o d u l e s
U t i l i t i e s
C o m m u n i t y
H i s t o r y
E x p a n d
p e r l t i e
( s o u r c e ,
C P A N )
Y o u a r e v i e w i n g t h e v e r s i o n o f t h i s d o c u m e n t a t i o n f r o m P e r l 5 . 0 0 5 _ 0 3 .
V i e w t h e l a t e s t v e r s i o n
●
N A M E
●
S Y N O P S I S
●
D E S C R I P T I O N
●
T y i n g S c a l a r s
●
T y i n g A r r a y s
●
T y i n g H a s h e s
●
T y i n g F i l e H a n d l e s
●
T h e u n t i e G o t c h a
●
S E E A L S O
●
B U G S
●
A U T H O R
# N A M E
p e r l t i e - h o w t o h i d e a n o b j e c t c l a s s i n a s i m p l e v a r i a b l e
# S Y N O P S I S
tie VARIABLE, CLASSNAME, LIST
$object = tied VARIABLE
untie VARIABLE
# D E S C R I P T I O N
P r i o r t o r e l e a s e 5 . 0 o f P e r l , a p r o g r a m m e r c o u l d u s e d b m o p e n ( ) t o c o n n e c t a n o n - d i s k d a t a b a s e i n t h e s t a n d a r d U n i x d b m ( 3 x ) f o r m a t m a g i c a l l y t o a % H A S H i n t h e i r p r o g r a m . H o w e v e r , t h e i r P e r l w a s e i t h e r b u i l t w i t h o n e p a r t i c u l a r d b m l i b r a r y o r a n o t h e r , b u t n o t b o t h , a n d y o u c o u l d n ' t e x t e n d t h i s m e c h a n i s m t o o t h e r p a c k a g e s o r t y p e s o f v a r i a b l e s .
N o w y o u c a n .
T h e t i e ( ) f u n c t i o n b i n d s a v a r i a b l e t o a c l a s s ( p a c k a g e ) t h a t w i l l p r o v i d e t h e i m p l e m e n t a t i o n f o r a c c e s s m e t h o d s f o r t h a t v a r i a b l e . O n c e t h i s m a g i c h a s b e e n p e r f o r m e d , a c c e s s i n g a t i e d v a r i a b l e a u t o m a t i c a l l y t r i g g e r s m e t h o d c a l l s i n t h e p r o p e r c l a s s . T h e c o m p l e x i t y o f t h e c l a s s i s h i d d e n b e h i n d m a g i c m e t h o d s c a l l s . T h e m e t h o d n a m e s a r e i n A L L C A P S , w h i c h i s a c o n v e n t i o n t h a t P e r l u s e s t o i n d i c a t e t h a t t h e y ' r e c a l l e d i m p l i c i t l y r a t h e r t h a n e x p l i c i t l y - - j u s t l i k e t h e B E G I N ( ) a n d E N D ( ) f u n c t i o n s .
I n t h e t i e ( ) c a l l , V A R I A B L E
i s t h e n a m e o f t h e v a r i a b l e t o b e e n c h a n t e d . C L A S S N A M E
i s t h e n a m e o f a c l a s s i m p l e m e n t i n g o b j e c t s o f t h e c o r r e c t t y p e . A n y a d d i t i o n a l a r g u m e n t s i n t h e L I S T
a r e p a s s e d t o t h e a p p r o p r i a t e c o n s t r u c t o r m e t h o d f o r t h a t c l a s s - - m e a n i n g T I E S C A L A R ( ) , T I E A R R A Y ( ) , T I E H A S H ( ) , o r T I E H A N D L E ( ) . ( T y p i c a l l y t h e s e a r e a r g u m e n t s s u c h a s m i g h t b e p a s s e d t o t h e d b m i n i t ( ) f u n c t i o n o f C . ) T h e o b j e c t r e t u r n e d b y t h e " n e w " m e t h o d i s a l s o r e t u r n e d b y t h e t i e ( ) f u n c t i o n , w h i c h w o u l d b e u s e f u l i f y o u w a n t e d t o a c c e s s o t h e r m e t h o d s i n C L A
S S N A M E
. ( Y o u d o n ' t a c t u a l l y h a v e t o r e t u r n a r e f e r e n c e t o a r i g h t " t y p e " ( e . g . , H A S H o r C L A S S N A M
E
) s o l o n g a s i t ' s a p r o p e r l y b l e s s e d o b j e c t . ) Y o u c a n a l s o r e t r i e v e a r e f e r e n c e t o t h e u n d e r l y i n g o b j e c t u s i n g t h e t i e d ( ) f u n c t i o n .
U n l i k e d b m o p e n ( ) , t h e t i e ( ) f u n c t i o n w i l l n o t u s e
or r e q u i r e
a m o d u l e f o r y o u - - y o u n e e d t o d o t h a t e x p l i c i t l y y o u r s e l f .
# T y i n g S c a l a r s
A c l a s s i m p l e m e n t i n g a t i e d s c a l a r s h o u l d d e f i n e t h e f o l l o w i n g m e t h o d s : T I E S C A L A R , F E T C H , S T O R E , a n d p o s s i b l y D E S T R O Y .
L e t ' s l o o k a t e a c h i n t u r n , u s i n g a s a n e x a m p l e a t i e c l a s s f o r s c a l a r s t h a t a l l o w s t h e u s e r t o d o s o m e t h i n g l i k e :
tie $his_speed, 'Nice', getppid();
tie $my_speed, 'Nice', $$;
A n d n o w w h e n e v e r e i t h e r o f t h o s e v a r i a b l e s i s a c c e s s e d , i t s c u r r e n t s y s t e m p r i o r i t y i s r e t r i e v e d a n d r e t u r n e d . I f t h o s e v a r i a b l e s a r e s e t , t h e n t h e p r o c e s s ' s p r i o r i t y i s c h a n g e d !
W e ' l l u s e J a r k k o H i e t a n i e m i < j h i @ i k i . f i > ' s B S D : : R e s o u r c e c l a s s ( n o t i n c l u d e d ) t o a c c e s s t h e P R I O _ P R O C E S S , P R I O _ M I N , a n d P R I O _ M A X c o n s t a n t s f r o m y o u r s y s t e m , a s w e l l a s t h e g e t p r i o r i t y ( ) a n d s e t p r i o r i t y ( ) s y s t e m c a l l s . H e r e ' s t h e p r e a m b l e o f t h e c l a s s .
package Nice;
use Carp;
use BSD::Resource;
use strict;
$Nice::DEBUG = 0 unless defined $Nice::DEBUG;
# T I E S C A L A R c l a s s n a m e , L I S T
T h i s i s t h e c o n s t r u c t o r f o r t h e c l a s s . T h a t m e a n s i t i s e x p e c t e d t o r e t u r n a b l e s s e d r e f e r e n c e t o a n e w s c a l a r ( p r o b a b l y a n o n y m o u s ) t h a t i t ' s c r e a t i n g . F o r e x a m p l e :
sub TIESCALAR {
my $class = shift;
my $pid = shift || $$; # 0 means me
if ($pid !~ /^\d+$/) {
carp "Nice::Tie::Scalar got non-numeric pid $pid" if $^W;
return undef;
}
unless (kill 0, $pid) { # EPERM or ERSCH, no doubt
carp "Nice::Tie::Scalar got bad pid $pid: $!" if $^W;
return undef;
}
return bless \$pid, $class;
}
T h i s t i e c l a s s h a s c h o s e n t o r e t u r n a n e r r o r r a t h e r t h a n r a i s i n g a n e x c e p t i o n i f i t s c o n s t r u c t o r s h o u l d f a i l . W h i l e t h i s i s h o w d b m o p e n ( ) w o r k s , o t h e r c l a s s e s m a y w e l l n o t w i s h t o b e s o f o r g i v i n g . I t c h e c k s t h e g l o b a l v a r i a b l e $ ^ W
t o s e e w h e t h e r t o e m i t a b i t o f n o i s e a n y w a y .
# F E T C H t h i s
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e t h e t i e d v a r i a b l e i s a c c e s s e d ( r e a d ) . I t t a k e s n o a r g u m e n t s b e y o n d i t s s e l f r e f e r e n c e , w h i c h i s t h e o b j e c t r e p r e s e n t i n g t h e s c a l a r w e ' r e d e a l i n g w i t h . B e c a u s e i n t h i s c a s e w e ' r e u s i n g j u s t a S C A L A R r e f f o r t h e t i e d s c a l a r o b j e c t , a s i m p l e $ $ s e l f a l l o w s t h e m e t h o d t o g e t a t t h e r e a l v a l u e s t o r e d t h e r e . I n o u r e x a m p l e b e l o w , t h a t r e a l v a l u e i s t h e p r o c e s s I D t o w h i c h w e ' v e t i e d o u r v a r i a b l e .
sub FETCH {
my $self = shift;
confess "wrong type" unless ref $self;
croak "usage error" if @_;
my $nicety;
local($!) = 0;
$nicety = getpriority(PRIO_PROCESS, $$self);
if ($!) { croak "getpriority failed: $!" }
return $nicety;
}
T h i s t i m e w e ' v e d e c i d e d t o b l o w u p ( r a i s e a n e x c e p t i o n ) i f t h e r e n i c e f a i l s - - t h e r e ' s n o p l a c e f o r u s t o r e t u r n a n e r r o r o t h e r w i s e , a n d i t ' s p r o b a b l y t h e r i g h t t h i n g t o d o .
# S T O R E t h i s , v a l u e
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e t h e t i e d v a r i a b l e i s s e t ( a s s i g n e d ) . B e y o n d i t s s e l f r e f e r e n c e , i t a l s o e x p e c t s o n e ( a n d o n l y o n e ) a r g u m e n t - - t h e n e w v a l u e t h e u s e r i s t r y i n g t o a s s i g n .
sub STORE {
my $self = shift;
confess "wrong type" unless ref $self;
my $new_nicety = shift;
croak "usage error" if @_;
if ($new_nicety < PRIO_MIN) {
carp sprintf
"WARNING: priority %d less than minimum system priority %d",
$new_nicety, PRIO_MIN if $^W;
$new_nicety = PRIO_MIN;
}
if ($new_nicety > PRIO_MAX) {
carp sprintf
"WARNING: priority %d greater than maximum system priority %d",
$new_nicety, PRIO_MAX if $^W;
$new_nicety = PRIO_MAX;
}
unless (defined setpriority(PRIO_PROCESS, $$self, $new_nicety)) {
confess "setpriority failed: $!";
}
return $new_nicety;
}
# D E S T R O Y t h i s
T h i s m e t h o d w i l l b e t r i g g e r e d w h e n t h e t i e d v a r i a b l e n e e d s t o b e d e s t r u c t e d . A s w i t h o t h e r o b j e c t c l a s s e s , s u c h a m e t h o d i s s e l d o m n e c e s s a r y , b e c a u s e P e r l d e a l l o c a t e s i t s m o r i b u n d o b j e c t ' s m e m o r y f o r y o u a u t o m a t i c a l l y - - t h i s i s n ' t C + + , y o u k n o w . W e ' l l u s e a D E S T R O Y m e t h o d h e r e f o r d e b u g g i n g p u r p o s e s o n l y .
sub DESTROY {
my $self = shift;
confess "wrong type" unless ref $self;
carp "[ Nice::DESTROY pid $$self ]" if $Nice::DEBUG;
}
T h a t ' s a b o u t a l l t h e r e i s t o i t . A c t u a l l y , i t ' s m o r e t h a n a l l t h e r e i s t o i t , b e c a u s e w e ' v e d o n e a f e w n i c e t h i n g s h e r e f o r t h e s a k e o f c o m p l e t e n e s s , r o b u s t n e s s , a n d g e n e r a l a e s t h e t i c s . S i m p l e r T I E S C A L A R c l a s s e s a r e c e r t a i n l y p o s s i b l e .
# T y i n g A r r a y s
A c l a s s i m p l e m e n t i n g a t i e d o r d i n a r y a r r a y s h o u l d d e f i n e t h e f o l l o w i n g m e t h o d s : T I E A R R A Y , F E T C H , S T O R E , F E T C H S I Z E , S T O R E S I Z E a n d p e r h a p s D E S T R O Y .
F E T C H S I Z E a n d S T O R E S I Z E a r e u s e d t o p r o v i d e $ # a r r a y
a n d e q u i v a l e n t s c a l a r ( @ a r r a y )
a c c e s s .
T h e m e t h o d s P O P , P U S H , S H I F T , U N S H I F T , S P L I C E a r e r e q u i r e d i f t h e p e r l o p e r a t o r w i t h t h e c o r r e s p o n d i n g ( b u t l o w e r c a s e ) n a m e i s t o o p e r a t e o n t h e t i e d a r r a y . T h e T i e : : A r r a y c l a s s c a n b e u s e d a s a b a s e c l a s s t o i m p l e m e n t t h e s e i n t e r m s o f t h e b a s i c f i v e m e t h o d s a b o v e .
I n a d d i t i o n E X T E N D w i l l b e c a l l e d w h e n p e r l w o u l d h a v e p r e - e x t e n d e d a l l o c a t i o n i n a r e a l a r r a y .
T h i s m e a n s t h a t t i e d a r r a y s a r e n o w c o m p l e t e . T h e e x a m p l e b e l o w n e e d s u p g r a d i n g t o i l l u s t r a t e t h i s . ( T h e d o c u m e n t a t i o n i n T i e : : A r r a y i s m o r e c o m p l e t e . )
F o r t h i s d i s c u s s i o n , w e ' l l i m p l e m e n t a n a r r a y w h o s e i n d i c e s a r e f i x e d a t i t s c r e a t i o n . I f y o u t r y t o a c c e s s a n y t h i n g b e y o n d t h o s e b o u n d s , y o u ' l l t a k e a n e x c e p t i o n . F o r e x a m p l e :
require Bounded_Array;
tie @ary, 'Bounded_Array', 2;
$| = 1;
for $i (0 .. 10) {
print "setting index $i: ";
$ary[$i] = 10 * $i;
$ary[$i] = 10 * $i;
print "value of elt $i now $ary[$i]\n";
}
T h e p r e a m b l e c o d e f o r t h e c l a s s i s a s f o l l o w s :
package Bounded_Array;
use Carp;
use strict;
# T I E A R R A Y c l a s s n a m e , L I S T
T h i s i s t h e c o n s t r u c t o r f o r t h e c l a s s . T h a t m e a n s i t i s e x p e c t e d t o r e t u r n a b l e s s e d r e f e r e n c e t h r o u g h w h i c h t h e n e w a r r a y ( p r o b a b l y a n a n o n y m o u s A R R A Y r e f ) w i l l b e a c c e s s e d .
I n o u r e x a m p l e , j u s t t o s h o w y o u t h a t y o u d o n ' t r e a l l y h a v e t o r e t u r n a n A R R A Y r e f e r e n c e , w e ' l l c h o o s e a H A S H r e f e r e n c e t o r e p r e s e n t o u r o b j e c t . A H A S H w o r k s o u t w e l l a s a g e n e r i c r e c o r d t y p e : t h e { B O U N D }
f i e l d w i l l s t o r e t h e m a x i m u m b o u n d a l l o w e d , a n d t h e { A R R A Y }
f i e l d w i l l h o l d t h e t r u e A R R A Y r e f . I f s o m e o n e o u t s i d e t h e c l a s s t r i e s t o d e r e f e r e n c e t h e o b j e c t r e t u r n e d ( d o u b t l e s s t h i n k i n g i t a n A R R A Y r e f ) , t h e y ' l l b l o w u p . T h i s j u s t g o e s t o s h o w y o u t h a t y o u s h o u l d r e s p e c t a n o b j e c t ' s p r i v a c y .
sub TIEARRAY {
my $class = shift;
my $bound = shift;
confess "usage: tie(\@ary, 'Bounded_Array', max_subscript)"
if @_ || $bound =~ /\D/;
return bless {
BOUND => $bound,
ARRAY => [],
}, $class;
}
# F E T C H t h i s , i n d e x
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e a n i n d i v i d u a l e l e m e n t t h e t i e d a r r a y i s a c c e s s e d ( r e a d ) . I t t a k e s o n e a r g u m e n t b e y o n d i t s s e l f r e f e r e n c e : t h e i n d e x w h o s e v a l u e w e ' r e t r y i n g t o f e t c h .
sub FETCH {
my($self,$idx) = @_;
if ($idx > $self->{BOUND}) {
confess "Array OOB: $idx > $self->{BOUND}";
}
return $self->{ARRAY}[$idx];
}
A s y o u m a y h a v e n o t i c e d , t h e n a m e o f t h e F E T C H m e t h o d ( e t a l . ) i s t h e s a m e f o r a l l a c c e s s e s , e v e n t h o u g h t h e c o n s t r u c t o r s d i f f e r i n n a m e s ( T I E S C A L A R v s T I E A R R A Y ) . W h i l e i n t h e o r y y o u c o u l d h a v e t h e s a m e c l a s s s e r v i c i n g s e v e r a l t i e d t y p e s , i n p r a c t i c e t h i s b e c o m e s c u m b e r s o m e , a n d i t ' s e a s i e s t t o k e e p t h e m a t s i m p l y o n e t i e t y p e p e r c l a s s .
# S T O R E t h i s , i n d e x , v a l u e
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e a n e l e m e n t i n t h e t i e d a r r a y i s s e t ( w r i t t e n ) . I t t a k e s t w o a r g u m e n t s b e y o n d i t s s e l f r e f e r e n c e : t h e i n d e x a t w h i c h w e ' r e t r y i n g t o s t o r e s o m e t h i n g a n d t h e v a l u e w e ' r e t r y i n g t o p u t t h e r e . F o r e x a m p l e :
sub STORE {
my($self, $idx, $value) = @_;
print "[STORE $value at $idx]\n" if _debug;
if ($idx > $self->{BOUND} ) {
confess "Array OOB: $idx > $self->{BOUND}";
}
return $self->{ARRAY}[$idx] = $value;
}
# D E S T R O Y t h i s
T h i s m e t h o d w i l l b e t r i g g e r e d w h e n t h e t i e d v a r i a b l e n e e d s t o b e d e s t r u c t e d . A s w i t h t h e s c a l a r t i e c l a s s , t h i s i s a l m o s t n e v e r n e e d e d i n a l a n g u a g e t h a t d o e s i t s o w n g a r b a g e c o l l e c t i o n , s o t h i s t i m e w e ' l l j u s t l e a v e i t o u t .
T h e c o d e w e p r e s e n t e d a t t h e t o p o f t h e t i e d a r r a y c l a s s a c c e s s e s m a n y e l e m e n t s o f t h e a r r a y , f a r m o r e t h a n w e ' v e s e t t h e b o u n d s t o . T h e r e f o r e , i t w i l l b l o w u p o n c e t h e y t r y t o a c c e s s b e y o n d t h e 2 n d e l e m e n t o f @ a r y , a s t h e f o l l o w i n g o u t p u t d e m o n s t r a t e s :
setting index 0: value of elt 0 now 0
setting index 1: value of elt 1 now 10
setting index 2: value of elt 2 now 20
setting index 3: Array OOB: 3 > 2 at Bounded_Array.pm line 39
Bounded_Array::FETCH called at testba line 12
# T y i n g H a s h e s
A s t h e f i r s t P e r l d a t a t y p e t o b e t i e d ( s e e d b m o p e n ( ) ) , h a s h e s h a v e t h e m o s t c o m p l e t e a n d u s e f u l t i e ( ) i m p l e m e n t a t i o n . A c l a s s i m p l e m e n t i n g a t i e d h a s h s h o u l d d e f i n e t h e f o l l o w i n g m e t h o d s : T I E H A S H i s t h e c o n s t r u c t o r . F E T C H a n d S T O R E a c c e s s t h e k e y a n d v a l u e p a i r s . E X I S T S r e p o r t s w h e t h e r a k e y i s p r e s e n t i n t h e h a s h , a n d D E L E T E d e l e t e s o n e . C L E A R e m p t i e s t h e h a s h b y d e l e t i n g a l l t h e k e y a n d v a l u e p a i r s . F I R S T K E Y a n d N E X T K E Y i m p l e m e n t t h e k e y s ( ) a n d e a c h ( ) f u n c t i o n s t o i t e r a t e o v e r a l l t h e k e y s . A n d D E S T R O Y i s c a l l e d w h e n t h e t i e d v a r i a b l e i s g a r b a g e c o l l e c t e d .
I f t h i s s e e m s l i k e a l o t , t h e n f e e l f r e e t o i n h e r i t f r o m m e r e l y t h e s t a n d a r d T i e : : H a s h m o d u l e f o r m o s t o f y o u r m e t h o d s , r e d e f i n i n g o n l y t h e i n t e r e s t i n g o n e s . S e e T i e : : H a s h f o r d e t a i l s .
R e m e m b e r t h a t P e r l d i s t i n g u i s h e s b e t w e e n a k e y n o t e x i s t i n g i n t h e h a s h , a n d t h e k e y e x i s t i n g i n t h e h a s h b u t h a v i n g a c o r r e s p o n d i n g v a l u e o f u n d e f
. T h e t w o p o s s i b i l i t i e s c a n b e t e s t e d w i t h t h e e x i s t s ( )
a n d d e f i n e d ( )
f u n c t i o n s .
H e r e ' s a n e x a m p l e o f a s o m e w h a t i n t e r e s t i n g t i e d h a s h c l a s s : i t g i v e s y o u a h a s h r e p r e s e n t i n g a p a r t i c u l a r u s e r ' s d o t f i l e s . Y o u i n d e x i n t o t h e h a s h w i t h t h e n a m e o f t h e f i l e ( m i n u s t h e d o t ) a n d y o u g e t b a c k t h a t d o t f i l e ' s c o n t e n t s . F o r e x a m p l e :
use DotFiles;
tie %dot, 'DotFiles';
if ( $dot{profile} =~ /MANPATH/ ||
$dot{login} =~ /MANPATH/ ||
$dot{cshrc} =~ /MANPATH/ )
{
print "you seem to set your MANPATH\n";
}
O r h e r e ' s a n o t h e r s a m p l e o f u s i n g o u r t i e d c l a s s :
tie %him, 'DotFiles', 'daemon';
foreach $f ( keys %him ) {
printf "daemon dot file %s is size %d\n",
$f, length $him{$f};
}
I n o u r t i e d h a s h D o t F i l e s e x a m p l e , w e u s e a r e g u l a r h a s h f o r t h e o b j e c t c o n t a i n i n g s e v e r a l i m p o r t a n t f i e l d s , o f w h i c h o n l y t h e {
L I S T }
f i e l d w i l l b e w h a t t h e u s e r t h i n k s o f a s t h e r e a l h a s h .
# U S E R
w h o s e d o t f i l e s t h i s o b j e c t r e p r e s e n t s
# H O M E
w h e r e t h o s e d o t f i l e s l i v e
# C L O B B E R
w h e t h e r w e s h o u l d t r y t o c h a n g e o r r e m o v e t h o s e d o t f i l e s
# L I S T
t h e h a s h o f d o t f i l e n a m e s a n d c o n t e n t m a p p i n g s
H e r e ' s t h e s t a r t o f D o t f i l e s . p m :
package DotFiles;
use Carp;
sub whowasi { (caller(1 ))[3 ] . '()' }
my $DEBUG = 0;
sub debug { $DEBUG = @_ ? shift : 1 }
F o r o u r e x a m p l e , w e w a n t t o b e a b l e t o e m i t d e b u g g i n g i n f o t o h e l p i n t r a c i n g d u r i n g d e v e l o p m e n t . W e k e e p a l s o o n e c o n v e n i e n c e f u n c t i o n a r o u n d i n t e r n a l l y t o h e l p p r i n t o u t w a r n i n g s ; w h o w a s i ( ) r e t u r n s t h e f u n c t i o n n a m e t h a t c a l l s i t .
H e r e a r e t h e m e t h o d s f o r t h e D o t F i l e s t i e d h a s h .
# T I E H A S H c l a s s n a m e , L I S T
T h i s i s t h e c o n s t r u c t o r f o r t h e c l a s s . T h a t m e a n s i t i s e x p e c t e d t o r e t u r n a b l e s s e d r e f e r e n c e t h r o u g h w h i c h t h e n e w o b j e c t ( p r o b a b l y b u t n o t n e c e s s a r i l y a n a n o n y m o u s h a s h ) w i l l b e a c c e s s e d .
H e r e ' s t h e c o n s t r u c t o r :
sub TIEHASH {
my $self = shift;
my $user = shift || $>;
my $dotdir = shift || '';
croak "usage: @{[&whowasi]} [USER [DOTDIR]]" if @_;
$user = getpwuid($user) if $user =~ /^\d+$/;
my $dir = (getpwnam($user))[7 ]
|| croak "@{[&whowasi]}: no user $user";
$dir .= "/$dotdir" if $dotdir;
my $node = {
USER => $user,
HOME => $dir,
LIST => {},
CLOBBER => 0,
};
opendir(DIR, $dir)
|| croak "@{[&whowasi]}: can't opendir $dir: $!";
foreach $dot ( grep /^\./ && -f "$dir/$_", readdir(DIR)) {
$dot =~ s/^\.//;
$node->{LIST}{$dot} = undef;
}
closedir DIR;
return bless $node, $self;
}
I t ' s p r o b a b l y w o r t h m e n t i o n i n g t h a t i f y o u ' r e g o i n g t o f i l e t e s t t h e r e t u r n v a l u e s o u t o f a r e a d d i r , y o u ' d b e t t e r p r e p e n d t h e d i r e c t o r y i n q u e s t i o n . O t h e r w i s e , b e c a u s e w e d i d n ' t c h d i r ( ) t h e r e , i t w o u l d h a v e b e e n t e s t i n g t h e w r o n g f i l e .
# F E T C H t h i s , k e y
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e a n e l e m e n t i n t h e t i e d h a s h i s a c c e s s e d ( r e a d ) . I t t a k e s o n e a r g u m e n t b e y o n d i t s s e l f r e f e r e n c e : t h e k e y w h o s e v a l u e w e ' r e t r y i n g t o f e t c h .
H e r e ' s t h e f e t c h f o r o u r D o t F i l e s e x a m p l e .
sub FETCH {
carp &whowasi if $DEBUG;
my $self = shift;
my $dot = shift;
my $dir = $self->{HOME};
my $file = "$dir/.$dot";
unless (exists $self->{LIST}->{$dot} || -f $file) {
carp "@{[&whowasi]}: no $dot file" if $DEBUG;
return undef;
}
if (defined $self->{LIST}->{$dot}) {
return $self->{LIST}->{$dot};
} else {
return $self->{LIST}->{$dot} = `cat $dir/.$dot`;
}
}
I t w a s e a s y t o w r i t e b y h a v i n g i t c a l l t h e U n i x c a t ( 1 ) c o m m a n d , b u t i t w o u l d p r o b a b l y b e m o r e p o r t a b l e t o o p e n t h e f i l e m a n u a l l y ( a n d s o m e w h a t m o r e e f f i c i e n t ) . O f c o u r s e , b e c a u s e d o t f i l e s a r e a U n i x y c o n c e p t , w e ' r e n o t t h a t c o n c e r n e d .
# S T O R E t h i s , k e y , v a l u e
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e a n e l e m e n t i n t h e t i e d h a s h i s s e t ( w r i t t e n ) . I t t a k e s t w o a r g u m e n t s b e y o n d i t s s e l f r e f e r e n c e : t h e i n d e x a t w h i c h w e ' r e t r y i n g t o s t o r e s o m e t h i n g , a n d t h e v a l u e w e ' r e t r y i n g t o p u t t h e r e .
H e r e i n o u r D o t F i l e s e x a m p l e , w e ' l l b e c a r e f u l n o t t o l e t t h e m t r y t o o v e r w r i t e t h e f i l e u n l e s s t h e y ' v e c a l l e d t h e c l o b b e r ( ) m e t h o d o n t h e o r i g i n a l o b j e c t r e f e r e n c e r e t u r n e d b y t i e ( ) .
sub STORE {
carp &whowasi if $DEBUG;
my $self = shift;
my $dot = shift;
my $value = shift;
my $file = $self->{HOME} . "/.$dot";
my $user = $self->{USER};
croak "@{[&whowasi]}: $file not clobberable"
unless $self->{CLOBBER};
open(F, "> $file") || croak "can't open $file: $!";
print F $value;
close(F );
}
I f t h e y w a n t e d t o c l o b b e r s o m e t h i n g , t h e y m i g h t s a y :
$ob = tie %daemon_dots, 'daemon';
$ob->clobber(1 );
$daemon_dots{signature} = "A true daemon\n";
A n o t h e r w a y t o l a y h a n d s o n a r e f e r e n c e t o t h e u n d e r l y i n g o b j e c t i s t o u s e t h e t i e d ( ) f u n c t i o n , s o t h e y m i g h t a l t e r n a t e l y h a v e s e t c l o b b e r u s i n g :
tie %daemon_dots, 'daemon';
tied(%daemon_dots)->clobber(1 );
T h e c l o b b e r m e t h o d i s s i m p l y :
sub clobber {
my $self = shift;
$self->{CLOBBER} = @_ ? shift : 1;
}
# D E L E T E t h i s , k e y
T h i s m e t h o d i s t r i g g e r e d w h e n w e r e m o v e a n e l e m e n t f r o m t h e h a s h , t y p i c a l l y b y u s i n g t h e d e l e t e ( ) f u n c t i o n . A g a i n , w e ' l l b e c a r e f u l t o c h e c k w h e t h e r t h e y r e a l l y w a n t t o c l o b b e r f i l e s .
sub DELETE {
carp &whowasi if $DEBUG;
my $self = shift;
my $dot = shift;
my $file = $self->{HOME} . "/.$dot";
croak "@{[&whowasi]}: won't remove file $file"
unless $self->{CLOBBER};
delete $self->{LIST}->{$dot};
my $success = unlink($file);
carp "@{[&whowasi]}: can't unlink $file: $!" unless $success;
$success;
}
T h e v a l u e r e t u r n e d b y D E L E T E b e c o m e s t h e r e t u r n v a l u e o f t h e c a l l t o d e l e t e ( ) . I f y o u w a n t t o e m u l a t e t h e n o r m a l b e h a v i o r o f d e l e t e ( ) , y o u s h o u l d r e t u r n w h a t e v e r F E T C H w o u l d h a v e r e t u r n e d f o r t h i s k e y . I n t h i s e x a m p l e , w e h a v e c h o s e n i n s t e a d t o r e t u r n a v a l u e w h i c h t e l l s t h e c a l l e r w h e t h e r t h e f i l e w a s s u c c e s s f u l l y d e l e t e d .
# C L E A R t h i s
T h i s m e t h o d i s t r i g g e r e d w h e n t h e w h o l e h a s h i s t o b e c l e a r e d , u s u a l l y b y a s s i g n i n g t h e e m p t y l i s t t o i t .
I n o u r e x a m p l e , t h a t w o u l d r e m o v e a l l t h e u s e r ' s d o t f i l e s ! I t ' s s u c h a d a n g e r o u s t h i n g t h a t t h e y ' l l h a v e t o s e t C L O B B E R t o s o m e t h i n g h i g h e r t h a n 1 t o m a k e i t h a p p e n .
sub CLEAR {
carp &whowasi if $DEBUG;
my $self = shift;
croak "@{[&whowasi]}: won't remove all dot files for $self->{USER}"
unless $self->{CLOBBER} > 1;
my $dot;
foreach $dot ( keys %{$self->{LIST}}) {
$self->DELETE($dot);
}
}
# E X I S T S t h i s , k e y
T h i s m e t h o d i s t r i g g e r e d w h e n t h e u s e r u s e s t h e e x i s t s ( ) f u n c t i o n o n a p a r t i c u l a r h a s h . I n o u r e x a m p l e , w e ' l l l o o k a t t h e { L
I S T }
h a s h e l e m e n t f o r t h i s :
sub EXISTS {
carp &whowasi if $DEBUG;
my $self = shift;
my $dot = shift;
return exists $self->{LIST}->{$dot};
}
# F I R S T K E Y t h i s
T h i s m e t h o d w i l l b e t r i g g e r e d w h e n t h e u s e r i s g o i n g t o i t e r a t e t h r o u g h t h e h a s h , s u c h a s v i a a k e y s ( ) o r e a c h ( ) c a l l .
sub FIRSTKEY {
carp &whowasi if $DEBUG;
my $self = shift;
my $a = keys %{$self->{LIST}}; # reset each() iterator
each %{$self->{LIST}}
}
# N E X T K E Y t h i s , l a s t k e y
T h i s m e t h o d g e t s t r i g g e r e d d u r i n g a k e y s ( ) o r e a c h ( ) i t e r a t i o n . I t h a s a s e c o n d a r g u m e n t w h i c h i s t h e l a s t k e y t h a t h a d b e e n a c c e s s e d . T h i s i s u s e f u l i f y o u ' r e c a r r y i n g a b o u t o r d e r i n g o r c a l l i n g t h e i t e r a t o r f r o m m o r e t h a n o n e s e q u e n c e , o r n o t r e a l l y s t o r i n g t h i n g s i n a h a s h a n y w h e r e .
F o r o u r e x a m p l e , w e ' r e u s i n g a r e a l h a s h s o w e ' l l d o j u s t t h e s i m p l e t h i n g , b u t w e ' l l h a v e t o g o t h r o u g h t h e L I S T f i e l d i n d i r e c t l y .
sub NEXTKEY {
carp &whowasi if $DEBUG;
my $self = shift;
return each %{ $self->{LIST} }
}
# D E S T R O Y t h i s
T h i s m e t h o d i s t r i g g e r e d w h e n a t i e d h a s h i s a b o u t t o g o o u t o f s c o p e . Y o u d o n ' t r e a l l y n e e d i t u n l e s s y o u ' r e t r y i n g t o a d d d e b u g g i n g o r h a v e a u x i l i a r y s t a t e t o c l e a n u p . H e r e ' s a v e r y s i m p l e f u n c t i o n :
sub DESTROY {
carp &whowasi if $DEBUG;
}
N o t e t h a t f u n c t i o n s s u c h a s k e y s ( ) a n d v a l u e s ( ) m a y r e t u r n h u g e l i s t s w h e n u s e d o n l a r g e o b j e c t s , l i k e D B M f i l e s . Y o u m a y p r e f e r t o u s e t h e e a c h ( ) f u n c t i o n t o i t e r a t e o v e r s u c h . E x a m p l e :
# print out history file offsets
use NDBM_File;
tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
while (($key,$val) = each %HIST) {
print $key, ' = ', unpack('L',$val), "\n";
}
untie(%HIST);
# T y i n g F i l e H a n d l e s
T h i s i s p a r t i a l l y i m p l e m e n t e d n o w .
A c l a s s i m p l e m e n t i n g a t i e d f i l e h a n d l e s h o u l d d e f i n e t h e f o l l o w i n g m e t h o d s : T I E H A N D L E , a t l e a s t o n e o f P R I N T , P R I N T F , W R I T E , R E A D L I N E , G E T C , R E A D , a n d p o s s i b l y C L O S E a n d D E S T R O Y .
I t i s e s p e c i a l l y u s e f u l w h e n p e r l i s e m b e d d e d i n s o m e o t h e r p r o g r a m , w h e r e o u t p u t t o S T D O U T a n d S T D E R R m a y h a v e t o b e r e d i r e c t e d i n s o m e s p e c i a l w a y . S e e n v i a n d t h e A p a c h e m o d u l e f o r e x a m p l e s .
I n o u r e x a m p l e w e ' r e g o i n g t o c r e a t e a s h o u t i n g h a n d l e .
package Shout;
# T I E H A N D L E c l a s s n a m e , L I S T
T h i s i s t h e c o n s t r u c t o r f o r t h e c l a s s . T h a t m e a n s i t i s e x p e c t e d t o r e t u r n a b l e s s e d r e f e r e n c e o f s o m e s o r t . T h e r e f e r e n c e c a n b e u s e d t o h o l d s o m e i n t e r n a l i n f o r m a t i o n .
sub TIEHANDLE { print "<shout>\n"; my $i; bless \$i, shift }
# W R I T E t h i s , L I S T
T h i s m e t h o d w i l l b e c a l l e d w h e n t h e h a n d l e i s w r i t t e n t o v i a t h e s y s w r i t e
f u n c t i o n .
sub WRITE {
$r = shift;
my($buf,$len,$offset) = @_;
print "WRITE called, \$buf=$buf, \$len=$len, \$offset=$offset";
}
# P R I N T t h i s , L I S T
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e t h e t i e d h a n d l e i s p r i n t e d t o w i t h t h e p r i n t ( )
f u n c t i o n . B e y o n d i t s s e l f r e f e r e n c e i t a l s o e x p e c t s t h e l i s t t h a t w a s p a s s e d t o t h e p r i n t f u n c t i o n .
sub PRINT { $r = shift; $$r++; print join($,,map(uc($_),@_)),$\ }
# P R I N T F t h i s , L I S T
T h i s m e t h o d w i l l b e t r i g g e r e d e v e r y t i m e t h e t i e d h a n d l e i s p r i n t e d t o w i t h t h e p r i n t f ( )
f u n c t i o n . B e y o n d i t s s e l f r e f e r e n c e i t a l s o e x p e c t s t h e f o r m a t a n d l i s t t h a t w a s p a s s e d t o t h e p r i n t f f u n c t i o n .
sub PRINTF {
shift;
my $fmt = shift;
print sprintf($fmt, @_)."\n";
}
# R E A D t h i s , L I S T
T h i s m e t h o d w i l l b e c a l l e d w h e n t h e h a n d l e i s r e a d f r o m v i a t h e r e a d
or s y s r e a d
f u n c t i o n s .
sub READ {
my $self = shift;
my $$bufref = \$_[0];
my(undef,$len,$offset) = @_;
print "READ called, \$buf=$bufref, \$len=$len, \$offset=$offset";
# add to $$bufref, set $len to number of characters read
$len;
}
# R E A D L I N E t h i s
T h i s m e t h o d w i l l b e c a l l e d w h e n t h e h a n d l e i s r e a d f r o m v i a < H A N D L E > . T h e m e t h o d s h o u l d r e t u r n u n d e f w h e n t h e r e i s n o m o r e d a t a .
sub READLINE { $r = shift; "READLINE called $$r times\n"; }
# G E T C t h i s
T h i s m e t h o d w i l l b e c a l l e d w h e n t h e g e t c
f u n c t i o n i s c a l l e d .
sub GETC { print "Don't GETC, Get Perl"; return "a"; }
# C L O S E t h i s
T h i s m e t h o d w i l l b e c a l l e d w h e n t h e h a n d l e i s c l o s e d v i a t h e c
l o s e
f u n c t i o n .
sub CLOSE { print "CLOSE called.\n" }
# D E S T R O Y t h i s
A s w i t h t h e o t h e r t y p e s o f t i e s , t h i s m e t h o d w i l l b e c a l l e d w h e n t h e t i e d h a n d l e i s a b o u t t o b e d e s t r o y e d . T h i s i s u s e f u l f o r d e b u g g i n g a n d p o s s i b l y c l e a n i n g u p .
sub DESTROY { print "</shout>\n" }
H e r e ' s h o w t o u s e o u r l i t t l e e x a m p l e :
tie(*FOO,'Shout');
print FOO "hello\n";
$a = 4; $b = 6;
print FOO $a, " plus ", $b, " equals ", $a + $b, "\n";
print <FOO>;
# T h e u n t i e
G o t c h a
I f y o u i n t e n d m a k i n g u s e o f t h e o b j e c t r e t u r n e d f r o m e i t h e r t i e ( ) o r t i e d ( ) , a n d i f t h e t i e ' s t a r g e t c l a s s d e f i n e s a d e s t r u c t o r , t h e r e i s a s u b t l e g o t c h a y o u m u s t g u a r d a g a i n s t .
A s s e t u p , c o n s i d e r t h i s ( a d m i t t e d l y r a t h e r c o n t r i v e d ) e x a m p l e o f a t i e ; a l l i t d o e s i s u s e a f i l e t o k e e p a l o g o f t h e v a l u e s a s s i g n e d t o a s c a l a r .
package Remember;
use strict;
use IO::File;
sub TIESCALAR {
my $class = shift;
my $filename = shift;
my $handle = new IO::File "> $filename"
or die "Cannot open $filename: $!\n";
print $handle "The Start\n";
bless {FH => $handle, Value => 0}, $class;
}
sub FETCH {
my $self = shift;
return $self->{Value};
}
sub STORE {
my $self = shift;
my $value = shift;
my $handle = $self->{FH};
print $handle "$value\n";
$self->{Value} = $value;
}
sub DESTROY {
my $self = shift;
my $handle = $self->{FH};
print $handle "The End\n";
close $handle;
}
1;
H e r e i s a n e x a m p l e t h a t m a k e s u s e o f t h i s t i e :
use strict;
use Remember;
my $fred;
tie $fred, 'Remember', 'myfile.txt';
$fred = 1;
$fred = 4;
$fred = 5;
untie $fred;
system "cat myfile.txt";
T h i s i s t h e o u t p u t w h e n i t i s e x e c u t e d :
The Start
1
4
5
The End
S o f a r s o g o o d . T h o s e o f y o u w h o h a v e b e e n p a y i n g a t t e n t i o n w i l l h a v e s p o t t e d t h a t t h e t i e d o b j e c t h a s n ' t b e e n u s e d s o f a r . S o l e t s a d d a n e x t r a m e t h o d t o t h e R e m e m b e r c l a s s t o a l l o w c o m m e n t s t o b e i n c l u d e d i n t h e f i l e - - s a y , s o m e t h i n g l i k e t h i s :
sub comment {
my $self = shift;
my $text = shift;
my $handle = $self->{FH};
print $handle $text, "\n";
}
A n d h e r e i s t h e p r e v i o u s e x a m p l e m o d i f i e d t o u s e t h e c o m m e n t
m e t h o d ( w h i c h r e q u i r e s t h e t i e d o b j e c t ) :
use strict;
use Remember;
my ($fred, $x);
$x = tie $fred, 'Remember', 'myfile.txt';
$fred = 1;
$fred = 4;
comment $x "changing...";
$fred = 5;
untie $fred;
system "cat myfile.txt";
W h e n t h i s c o d e i s e x e c u t e d t h e r e i s n o o u t p u t . H e r e ' s w h y :
W h e n a v a r i a b l e i s t i e d , i t i s a s s o c i a t e d w i t h t h e o b j e c t w h i c h i s t h e r e t u r n v a l u e o f t h e T I E S C A L A R , T I E A R R A Y , o r T I E H A S H f u n c t i o n . T h i s o b j e c t n o r m a l l y h a s o n l y o n e r e f e r e n c e , n a m e l y , t h e i m p l i c i t r e f e r e n c e f r o m t h e t i e d v a r i a b l e . W h e n u n t i e ( ) i s c a l l e d , t h a t r e f e r e n c e i s d e s t r o y e d . T h e n , a s i n t h e f i r s t e x a m p l e a b o v e , t h e o b j e c t ' s d e s t r u c t o r ( D E S T R O Y ) i s c a l l e d , w h i c h i s n o r m a l f o r o b j e c t s t h a t h a v e n o m o r e v a l i d r e f e r e n c e s ; a n d t h u s t h e f i l e i s c l o s e d .
I n t h e s e c o n d e x a m p l e , h o w e v e r , w e h a v e s t o r e d a n o t h e r r e f e r e n c e t o t h e t i e d o b j e c t i n $ x
. T h a t m e a n s t h a t w h e n u n t i e ( ) g e t s c a l l e d t h e r e w i l l s t i l l b e a v a l i d r e f e r e n c e t o t h e o b j e c t i n e x i s t e n c e , s o t h e d e s t r u c t o r i s n o t c a l l e d a t t h a t t i m e , a n d t h u s t h e f i l e i s n o t c l o s e d . T h e r e a s o n t h e r e i s n o o u t p u t i s b e c a u s e t h e f i l e b u f f e r s h a v e n o t b e e n f l u s h e d t o d i s k .
N o w t h a t y o u k n o w w h a t t h e p r o b l e m i s , w h a t c a n y o u d o t o a v o i d i t ? W e l l , t h e g o o d o l d - w
f l a g w i l l s p o t a n y i n s t a n c e s w h e r e y o u c a l l u n t i e ( ) a n d t h e r e a r e s t i l l v a l i d r e f e r e n c e s t o t h e t i e d o b j e c t . I f t h e s e c o n d s c r i p t a b o v e i s r u n w i t h t h e - w
f l a g , P e r l p r i n t s t h i s w a r n i n g m e s s a g e :
untie attempted while 1 inner references still exist
T o g e t t h e s c r i p t t o w o r k p r o p e r l y a n d s i l e n c e t h e w a r n i n g m a k e s u r e t h e r e a r e n o v a l i d r e f e r e n c e s t o t h e t i e d o b j e c t b e f o r e u n t i e ( ) i s c a l l e d :
undef $x;
untie $fred;
# S E E A L S O
S e e D B _ F i l e or C o n f i g f o r s o m e i n t e r e s t i n g t i e ( ) i m p l e m e n t a t i o n s .
# B U G S
T i e d a r r a y s a r e i n c o m p l e t e . T h e y a r e a l s o d i s t i n c t l y l a c k i n g s o m e t h i n g f o r t h e $ # A R R A Y
a c c e s s ( w h i c h i s h a r d , a s i t ' s a n l v a l u e ) , a s w e l l a s t h e o t h e r o b v i o u s a r r a y f u n c t i o n s , l i k e p u s h ( ) , p o p ( ) , s h i f t ( ) , u n s h i f t ( ) , a n d s p l i c e ( ) .
Y o u c a n n o t e a s i l y t i e a m u l t i l e v e l d a t a s t r u c t u r e ( s u c h a s a h a s h o f h a s h e s ) t o a d b m f i l e . T h e f i r s t p r o b l e m i s t h a t a l l b u t G D B M a n d B e r k e l e y D B h a v e s i z e l i m i t a t i o n s , b u t b e y o n d t h a t , y o u a l s o h a v e p r o b l e m s w i t h h o w r e f e r e n c e s a r e t o b e r e p r e s e n t e d o n d i s k . O n e e x p e r i m e n t a l m o d u l e t h a t d o e s a t t e m p t t o a d d r e s s t h i s n e e d p a r t i a l l y i s t h e M L D B M m o d u l e . C h e c k y o u r n e a r e s t C P A N s i t e a s d e s c r i b e d i n p e r l m o d l i b f o r s o u r c e c o d e t o M L D B M .
# A U T H O R
T o m C h r i s t i a n s e n
T I E H A N D L E b y S v e n V e r d o o l a e g e < s k i m o @ d n s . u f s i a . a c . b e > a n d D o u g M a c E a c h e r n < d o u g m @ o s f . o r g >
P e r l d o c B r o w s e r i s m a i n t a i n e d b y D a n B o o k ( D B O O K ) . P l e a s e c o n t a c t h i m v i a t h e G i t H u b i s s u e t r a c k e r or e m a i l r e g a r d i n g a n y i s s u e s w i t h t h e s i t e i t s e l f , s e a r c h , o r r e n d e r i n g o f d o c u m e n t a t i o n .
T h e P e r l d o c u m e n t a t i o n i s m a i n t a i n e d b y t h e P e r l 5 P o r t e r s i n t h e d e v e l o p m e n t o f P e r l . P l e a s e c o n t a c t t h e m v i a t h e P e r l i s s u e t r a c k e r , t h e m a i l i n g l i s t , o r I R C t o r e p o r t a n y i s s u e s w i t h t h e c o n t e n t s o r f o r m a t o f t h e d o c u m e n t a t i o n .