P e r l d o c B r o w s e r
●
5 . 4 0 . 0
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 s u b
( 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 . 4 0 . 0 .
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
●
S i g n a t u r e s
●
P r i v a t e V a r i a b l e s v i a m y ( )
●
P e r s i s t e n t P r i v a t e V a r i a b l e s
●
P e r s i s t e n t v a r i a b l e s v i a s t a t e ( )
●
P e r s i s t e n t v a r i a b l e s w i t h c l o s u r e s
●
T e m p o r a r y V a l u e s v i a l o c a l ( )
●
G r a m m a t i c a l n o t e o n l o c a l ( )
●
L o c a l i z a t i o n o f s p e c i a l v a r i a b l e s
●
L o c a l i z a t i o n o f g l o b s
●
L o c a l i z a t i o n o f e l e m e n t s o f c o m p o s i t e t y p e s
●
L o c a l i z e d d e l e t i o n o f e l e m e n t s o f c o m p o s i t e t y p e s
●
L v a l u e s u b r o u t i n e s
●
L e x i c a l S u b r o u t i n e s
●
s t a t e s u b v s m y s u b
●
o u r s u b r o u t i n e s
●
P a s s i n g S y m b o l T a b l e E n t r i e s ( t y p e g l o b s )
●
W h e n t o S t i l l U s e l o c a l ( )
●
P a s s b y R e f e r e n c e
●
P r o t o t y p e s
●
C o n s t a n t F u n c t i o n s
●
O v e r r i d i n g B u i l t - i n F u n c t i o n s
●
A u t o l o a d i n g
●
S u b r o u t i n e A t t r i b u t e s
●
S E E A L S O
# N A M E
p e r l s u b - P e r l s u b r o u t i n e s ( u s e r - d e f i n e d f u n c t i o n s )
# S Y N O P S I S
T o d e c l a r e s u b r o u t i n e s :
sub NAME; # A "forward" declaration.
sub NAME(PROTO); # ditto, but with prototypes
sub NAME : ATTRS; # with attributes
sub NAME(PROTO) : ATTRS; # with attributes and prototypes
sub NAME BLOCK # A declaration and a definition.
sub NAME(PROTO) BLOCK # ditto, but with prototypes
sub NAME : ATTRS BLOCK # with attributes
sub NAME(PROTO) : ATTRS BLOCK # with prototypes and attributes
use feature 'signatures';
sub NAME(SIG) BLOCK # with signature
sub NAME :ATTRS (SIG) BLOCK # with signature, attributes
sub NAME :prototype(PROTO) (SIG) BLOCK # with signature, prototype
T o d e f i n e a n a n o n y m o u s s u b r o u t i n e a t r u n t i m e :
$subref = sub BLOCK; # no proto
$subref = sub (PROTO) BLOCK; # with proto
$subref = sub : ATTRS BLOCK; # with attributes
$subref = sub (PROTO) : ATTRS BLOCK; # with proto and attributes
use feature 'signatures';
$subref = sub (SIG) BLOCK; # with signature
$subref = sub : ATTRS(SIG) BLOCK; # with signature, attributes
T o i m p o r t s u b r o u t i n e s :
use MODULE qw(NAME1 NAME2 NAME3);
T o c a l l s u b r o u t i n e s :
NAME(LIST); # Regular subroutine call.
NAME LIST; # Parentheses optional if predeclared/imported.
&NAME(LIST); # Circumvent prototypes.
&NAME; # Makes current @_ visible to called subroutine.
# D E S C R I P T I O N
L i k e m a n y l a n g u a g e s , P e r l p r o v i d e s f o r u s e r - d e f i n e d s u b r o u t i n e s . T h e s e m a y b e l o c a t e d a n y w h e r e i n t h e m a i n p r o g r a m , l o a d e d i n f r o m o t h e r f i l e s v i a t h e do
, r e q u i r
e
, o r u s e
k e y w o r d s , o r g e n e r a t e d o n t h e f l y u s i n g e v a l
o r a n o n y m o u s s u b r o u t i n e s . Y o u c a n e v e n c a l l a f u n c t i o n i n d i r e c t l y u s i n g a v a r i a b l e c o n t a i n i n g i t s n a m e o r a C O D E r e f e r e n c e .
T h e P e r l m o d e l f o r f u n c t i o n c a l l a n d r e t u r n v a l u e s i s s i m p l e : a l l f u n c t i o n s a r e p a s s e d a s p a r a m e t e r s o n e s i n g l e f l a t l i s t o f s c a l a r s , a n d a l l f u n c t i o n s l i k e w i s e r e t u r n t o t h e i r c a l l e r o n e s i n g l e f l a t l i s t o f s c a l a r s . A n y a r r a y s o r h a s h e s i n t h e s e c a l l a n d r e t u r n l i s t s w i l l c o l l a p s e , l o s i n g t h e i r i d e n t i t i e s - - b u t y o u m a y a l w a y s u s e p a s s - b y - r e f e r e n c e i n s t e a d t o a v o i d t h i s . B o t h c a l l a n d r e t u r n l i s t s m a y c o n t a i n a s m a n y o r a s f e w s c a l a r e l e m e n t s a s y o u ' d l i k e . ( O f t e n a f u n c t i o n w i t h o u t a n e x p l i c i t r e t u r n s t a t e m e n t i s c a l l e d a s u b r o u t i n e , b u t t h e r e ' s r e a l l y n o d i f f e r e n c e f r o m P e r l ' s p e r s p e c t i v e . )
I n a s u b r o u t i n e t h a t u s e s s i g n a t u r e s ( s e e " S i g n a t u r e s " b e l o w ) , a r g u m e n t s a r e a s s i g n e d i n t o l e x i c a l v a r i a b l e s i n t r o d u c e d b y t h e s i g n a t u r e . I n t h e c u r r e n t i m p l e m e n t a t i o n o f P e r l t h e y a r e a l s o a c c e s s i b l e i n t h e @ _
a r r a y i n t h e s a m e w a y a s f o r n o n - s i g n a t u r e s u b r o u t i n e s , b u t a c c e s s i n g t h e m i n t h i s m a n n e r i s n o w d i s c o u r a g e d i n s i d e s u c h a s i g n a t u r e - u s i n g s u b r o u t i n e .
I n a s u b r o u t i n e t h a t d o e s n o t u s e s i g n a t u r e s , a n y a r g u m e n t s p a s s e d i n s h o w u p i n t h e a r r a y @ _
. T h e r e f o r e , i f y o u c a l l e d a f u n c t i o n w i t h t w o a r g u m e n t s , t h o s e w o u l d b e s t o r e d i n $ _ [ 0 ]
a n d $ _ [ 1 ]
. T h e a r r a y @ _
i s a l o c a l a r r a y , b u t i t s e l e m e n t s a r e a l i a s e s f o r t h e a c t u a l s c a l a r p a r a m e t e r s . I n p a r t i c u l a r , i f a n e l e m e n t $ _ [ 0 ]
i s u p d a t e d , t h e c o r r e s p o n d i n g a r g u m e n t i s u p d a t e d ( o r a n e r r o r o c c u r s i f i t i s n o t u p d a t a b l e ) . I f a n a r g u m e n t i s a n a r r a y o r h a s h e l e m e n t w h i c h d i d n o t e x i s t w h e n t h e f u n c t i o n w a s c a l l e d , t h a t e l e m e n t i s c r e a t e d o n l y w h e n ( a n d i f ) i t i s m o d i f i e d o r a r e f e r e n c e t o i t i s t a k e n . ( S o m e e a r l i e r v e r s i o n s o f P e r l c r e a t e d t h e e l e m e n t w h e t h e r o r n o t t h e e l e m e n t w a s a s s i g n e d t o . ) A s s i g n i n g t o t h e w h o l e a r r a y @ _
r e m o v e s t h a t a l i a s i n g , a n d d o e s n o t u p d a t e a n y a r g u m e n t s .
W h e n n o t u s i n g s i g n a t u r e s , P e r l d o e s n o t o t h e r w i s e p r o v i d e a m e a n s t o c r e a t e n a m e d f o r m a l p a r a m e t e r s . I n p r a c t i c e a l l y o u d o i s a s s i g n t o a m y ( )
l i s t o f t h e s e . V a r i a b l e s t h a t a r e n ' t d e c l a r e d t o b e p r i v a t e a r e g l o b a l v a r i a b l e s . F o r g o r y d e t a i l s o n c r e a t i n g p r i v a t e v a r i a b l e s , s e e " P r i v a t e V a r i a b l e s v i a m y ( ) " a n d " T e m p o r a r y V a l u e s v i a l o c a l ( ) " . T o c r e a t e p r o t e c t e d e n v i r o n m e n t s f o r a s e t o f f u n c t i o n s i n a s e p a r a t e p a c k a g e ( a n d p r o b a b l y a s e p a r a t e f i l e ) , s e e " P a c k a g e s " i n p e r l m o d .
A r e t u r n
s t a t e m e n t m a y b e u s e d t o e x i t a s u b r o u t i n e , o p t i o n a l l y s p e c i f y i n g t h e r e t u r n e d v a l u e , w h i c h w i l l b e e v a l u a t e d i n t h e a p p r o p r i a t e c o n t e x t ( l i s t , s c a l a r , o r v o i d ) d e p e n d i n g o n t h e c o n t e x t o f t h e s u b r o u t i n e c a l l . I f y o u s p e c i f y n o r e t u r n v a l u e , t h e s u b r o u t i n e r e t u r n s a n e m p t y l i s t i n l i s t c o n t e x t , t h e u n d e f i n e d v a l u e i n s c a l a r c o n t e x t , o r n o t h i n g i n v o i d c o n t e x t . I f y o u r e t u r n o n e o r m o r e a g g r e g a t e s ( a r r a y s a n d h a s h e s ) , t h e s e w i l l b e f l a t t e n e d t o g e t h e r i n t o o n e l a r g e i n d i s t i n g u i s h a b l e l i s t .
I f n o r e t u r n
i s f o u n d a n d i f t h e l a s t s t a t e m e n t i s a n e x p r e s s i o n , i t s v a l u e i s r e t u r n e d . I f t h e l a s t s t a t e m e n t i s a l o o p c o n t r o l s t r u c t u r e l i k e a f o r e a c h
o r a w h
i l e
, t h e r e t u r n e d v a l u e i s u n s p e c i f i e d . T h e e m p t y s u b r e t u r n s t h e e m p t y l i s t .
E x a m p l e :
sub max {
my $max = shift(@_);
foreach $foo (@_) {
$max = $foo if $max < $foo;
}
return $max;
}
$bestday = max($mon,$tue,$wed,$thu,$fri);
E x a m p l e :
# get a line, combining continuation lines
# that start with whitespace
sub get_line {
$thisline = $lookahead; # global variables!
LINE: while (defined($lookahead = <STDIN>)) {
if ($lookahead =~ /^[ \t]/) {
$thisline .= $lookahead;
}
else {
last LINE;
}
}
return $thisline;
}
$lookahead = <STDIN>; # get first line
while (defined($line = get_line())) {
...
}
A s s i g n i n g t o a l i s t o f p r i v a t e v a r i a b l e s t o n a m e y o u r a r g u m e n t s :
sub maybeset {
my($key, $value) = @_;
$Foo{$key} = $value unless $Foo{$key};
}
B e c a u s e t h e a s s i g n m e n t c o p i e s t h e v a l u e s , t h i s a l s o h a s t h e e f f e c t o f t u r n i n g c a l l - b y - r e f e r e n c e i n t o c a l l - b y - v a l u e . O t h e r w i s e a f u n c t i o n i s f r e e t o d o i n - p l a c e m o d i f i c a t i o n s o f @ _
a n d c h a n g e i t s c a l l e r ' s v a l u e s .
upcase_in($v1, $v2); # this changes $v1 and $v2
sub upcase_in {
for (@_) { tr/a-z/A-Z/ }
}
Y o u a r e n ' t a l l o w e d t o m o d i f y c o n s t a n t s i n t h i s w a y , o f c o u r s e . I f a n a r g u m e n t w e r e a c t u a l l y l i t e r a l a n d y o u t r i e d t o c h a n g e i t , y o u ' d t a k e a ( p r e s u m a b l y f a t a l ) e x c e p t i o n . F o r e x a m p l e , t h i s w o n ' t w o r k :
upcase_in("frederick");
I t w o u l d b e m u c h s a f e r i f t h e u p
c a s e _ i n ( )
f u n c t i o n w e r e w r i t t e n t o r e t u r n a c o p y o f i t s p a r a m e t e r s i n s t e a d o f c h a n g i n g t h e m i n p l a c e :
($v3, $v4) = upcase($v1, $v2); # this doesn't change $v1 and $v2
sub upcase {
return unless defined wantarray; # void context, do nothing
my @parms = @_;
for (@parms) { tr/a-z/A-Z/ }
return wantarray ? @parms : $parms[0];
}
N o t i c e h o w t h i s ( u n p r o t o t y p e d ) f u n c t i o n d o e s n ' t c a r e w h e t h e r i t w a s p a s s e d r e a l s c a l a r s o r a r r a y s . P e r l s e e s a l l a r g u m e n t s a s o n e b i g , l o n g , f l a t p a r a m e t e r l i s t i n @ _
. T h i s i s o n e a r e a w h e r e P e r l ' s s i m p l e a r g u m e n t - p a s s i n g s t y l e s h i n e s . T h e u p c a s e ( )
f u n c t i o n w o u l d w o r k p e r f e c t l y w e l l w i t h o u t c h a n g i n g t h e u p c a s e ( )
d e f i n i t i o n e v e n i f w e f e d i t t h i n g s l i k e t h i s :
@newlist = upcase(@list1, @list2);
@newlist = upcase( split /:/, $var );
D o n o t , h o w e v e r , b e t e m p t e d t o d o t h i s :
(@x, @y) = upcase(@list1, @list2);
L i k e t h e f l a t t e n e d i n c o m i n g p a r a m e t e r l i s t , t h e r e t u r n l i s t i s a l s o f l a t t e n e d o n r e t u r n . S o a l l y o u h a v e m a n a g e d t o d o h e r e i s s t o r e d e v e r y t h i n g i n @ x
a n d m a d e @ y
e m p t y . S e e " P a s s b y R e f e r e n c e " f o r a l t e r n a t i v e s .
A s u b r o u t i n e m a y b e c a l l e d u s i n g a n e x p l i c i t &
p r e f i x . T h e &
i s o p t i o n a l i n m o d e r n P e r l , a s a r e p a r e n t h e s e s i f t h e s u b r o u t i n e h a s b e e n p r e d e c l a r e d . T h e &
is n o t o p t i o n a l w h e n j u s t n a m i n g t h e s u b r o u t i n e , s u c h a s w h e n i t ' s u s e d a s a n a r g u m e n t t o d e f i n e d ( ) o r u n d e f ( ) . N o r i s i t o p t i o n a l w h e n y o u w a n t t o d o a n i n d i r e c t s u b r o u t i n e c a l l w i t h a s u b r o u t i n e n a m e o r r e f e r e n c e u s i n g t h e & $ s u b r e f
( )
or & { $ s u b r e f } ( )
c o n s t r u c t s , a l t h o u g h t h e $ s u b r e f - > ( )
n o t a t i o n s o l v e s t h a t p r o b l e m . S e e p e r l r e f f o r m o r e a b o u t a l l t h a t .
S u b r o u t i n e s m a y b e c a l l e d r e c u r s i v e l y . I f a s u b r o u t i n e i s c a l l e d u s i n g t h e &
f o r m , t h e a r g u m e n t l i s t i s o p t i o n a l , a n d i f o m i t t e d , n o @ _
a r r a y i s s e t u p f o r t h e s u b r o u t i n e : t h e @ _
a r r a y a t t h e t i m e o f t h e c a l l i s v i s i b l e t o s u b r o u t i n e i n s t e a d . T h i s i s a n e f f i c i e n c y m e c h a n i s m t h a t n e w u s e r s m a y w i s h t o a v o i d .
&foo(1,2,3); # pass three arguments
foo(1,2,3); # the same
foo(); # pass an empty argument list
&foo(); # the same
&foo; # foo() gets current args, like foo(@_)!
use strict 'subs';
foo; # like foo() iff sub foo predeclared, else
# a compile-time error
no strict 'subs';
foo; # like foo() iff sub foo predeclared, else
# a literal string "foo"
N o t o n l y d o e s t h e &
f o r m m a k e t h e a r g u m e n t l i s t o p t i o n a l , i t a l s o d i s a b l e s a n y p r o t o t y p e c h e c k i n g o n a r g u m e n t s y o u d o p r o v i d e . T h i s i s p a r t l y f o r h i s t o r i c a l r e a s o n s , a n d p a r t l y f o r h a v i n g a c o n v e n i e n t w a y t o c h e a t i f y o u k n o w w h a t y o u ' r e d o i n g . S e e " P r o t o t y p e s " b e l o w .
S i n c e P e r l 5 . 1 6 . 0 , t h e _ _ S U B _ _
t o k e n i s a v a i l a b l e u n d e r u s e f e a t
u r e ' c u r r e n t _ s u b '
a n d u s e v 5 . 1 6
. I t w i l l e v a l u a t e t o a r e f e r e n c e t o t h e c u r r e n t l y - r u n n i n g s u b , w h i c h a l l o w s f o r r e c u r s i v e c a l l s w i t h o u t k n o w i n g y o u r s u b r o u t i n e ' s n a m e .
use v5.16;
my $factorial = sub {
my ($x) = @_;
return 1 if $x == 1;
return($x * __SUB__->( $x - 1 ) );
};
T h e b e h a v i o r o f _ _ S U B _ _
w i t h i n a r e g e x c o d e b l o c k ( s u c h a s / ( ? { . .
. } ) /
) i s s u b j e c t t o c h a n g e .
S u b r o u t i n e s w h o s e n a m e s a r e i n a l l u p p e r c a s e a r e r e s e r v e d t o t h e P e r l c o r e , a s a r e m o d u l e s w h o s e n a m e s a r e i n a l l l o w e r c a s e . A s u b r o u t i n e i n a l l c a p i t a l s i s a l o o s e l y - h e l d c o n v e n t i o n m e a n i n g i t w i l l b e c a l l e d i n d i r e c t l y b y t h e r u n - t i m e s y s t e m i t s e l f , u s u a l l y d u e t o a t r i g g e r e d e v e n t . S u b r o u t i n e s w h o s e n a m e s t a r t w i t h a l e f t p a r e n t h e s i s a r e a l s o r e s e r v e d t h e s a m e w a y . T h e f o l l o w i n g i s a l i s t o f s o m e s u b r o u t i n e s t h a t c u r r e n t l y d o s p e c i a l , p r e - d e f i n e d t h i n g s .
# d o c u m e n t e d l a t e r i n t h i s d o c u m e n t
A U T O L O A D
# d o c u m e n t e d i n p e r l m o d
C L O N E
, C L O N E _ S K I P
# d o c u m e n t e d i n p e r l o b j
D E S T R O Y
, D O E S
# d o c u m e n t e d i n p e r l t i e
B I N M O D E
, C L E A R
, C L O S E
, D E L E T E
, D E S T R O Y
, E O F
, E X I S T S
, E X T E N D
, F
E T C H
, F E T C H S I Z E
, F I L E N O
, F I R S T K
E Y
, G E T C
, N E X T K E Y
, O P E N
, P O P
, P
R I N T
, P R I N T F
, P U S H
, R E A D
, R E A D L
I N E
, S C A L A R
, S E E K
, S H I F T
, S P L I C
E
, S T O R E
, S T O R E S I Z E
, T E L L
, T I E A
R R A Y
, T I E H A N D L E
, T I E H A S H
, T I E S C
A L A R
, U N S H I F T
, U N T I E
, W R I T E
# d o c u m e n t e d i n P e r l I O : : v i a
B I N M O D E
, C L E A R E R R
, C L O S E
, E O F
, E R R O R
, F D O P E N
, F I L E N O
, F I L L
, F L
U S H
, O P E N
, P O P P E D
, P U S H E D
, R E A D
, S E E K
, S E T L I N E B U F
, S Y S O P E N
, T E L
L
, U N R E A D
, U T F 8
, W R I T E
# d o c u m e n t e d i n p e r l f u n c
i m p o r t
, u n i m p o r t
, I N C
# d o c u m e n t e d i n U N I V E R S A L
V E R S I O N
# d o c u m e n t e d i n p e r l d e b g u t s
D B : : D B
, D B : : s u b
, D B : : l s u b
, D B : :
g o t o
, D B : : p o s t p o n e d
# u n d o c u m e n t e d , u s e d i n t e r n a l l y b y t h e o v e r l o a d f e a t u r e
a n y s t a r t i n g w i t h (
T h e B E G I N
, U N I T C H E C K
, C H E C K
, I N I
T
a n d E N D
s u b r o u t i n e s a r e n o t s o m u c h s u b r o u t i n e s a s n a m e d s p e c i a l c o d e b l o c k s , o f w h i c h y o u c a n h a v e m o r e t h a n o n e i n a p a c k a g e , a n d w h i c h y o u c a n n o t c a l l e x p l i c i t l y . S e e " B E G I N , U N I T C H E C K , C H E C K , I N I T a n d E N D " i n p e r l m o d
# S i g n a t u r e s
P e r l h a s a f a c i l i t y t o a l l o w a s u b r o u t i n e ' s f o r m a l p a r a m e t e r s t o b e d e c l a r e d b y s p e c i a l s y n t a x , s e p a r a t e f r o m t h e p r o c e d u r a l c o d e o f t h e s u b r o u t i n e b o d y . T h e f o r m a l p a r a m e t e r l i s t i s k n o w n a s a s i g n a t u r e .
T h i s f a c i l i t y m u s t b e e n a b l e d b e f o r e i t c a n b e u s e d . I t i s e n a b l e d a u t o m a t i c a l l y b y a u s e v 5 . 3 6
( o r h i g h e r ) d e c l a r a t i o n , o r m o r e d i r e c t l y b y u s e f e a t u r e ' s i g n a t
u r e s '
, i n t h e c u r r e n t s c o p e .
T h e s i g n a t u r e i s p a r t o f a s u b r o u t i n e ' s b o d y . N o r m a l l y t h e b o d y o f a s u b r o u t i n e i s s i m p l y a b r a c e d b l o c k o f c o d e , b u t w h e n u s i n g a s i g n a t u r e , t h e s i g n a t u r e i s a p a r e n t h e s i s e d l i s t t h a t g o e s i m m e d i a t e l y b e f o r e t h e b l o c k , a f t e r a n y n a m e o r a t t r i b u t e s .
F o r e x a m p l e ,
sub foo :lvalue ($x, $y = 1, @z) { .... }
T h e s i g n a t u r e d e c l a r e s l e x i c a l v a r i a b l e s t h a t a r e i n s c o p e f o r t h e b l o c k . W h e n t h e s u b r o u t i n e i s c a l l e d , t h e s i g n a t u r e t a k e s c o n t r o l f i r s t . I t p o p u l a t e s t h e s i g n a t u r e v a r i a b l e s f r o m t h e l i s t o f a r g u m e n t s t h a t w e r e p a s s e d . I f t h e a r g u m e n t l i s t d o e s n ' t m e e t t h e r e q u i r e m e n t s o f t h e s i g n a t u r e , t h e n i t w i l l t h r o w a n e x c e p t i o n . W h e n t h e s i g n a t u r e p r o c e s s i n g i s c o m p l e t e , c o n t r o l p a s s e s t o t h e b l o c k .
P o s i t i o n a l p a r a m e t e r s a r e h a n d l e d b y s i m p l y n a m i n g s c a l a r v a r i a b l e s i n t h e s i g n a t u r e . F o r e x a m p l e ,
sub foo ($left, $right) {
return $left + $right;
}
t a k e s t w o p o s i t i o n a l p a r a m e t e r s , w h i c h m u s t b e f i l l e d a t r u n t i m e b y t w o a r g u m e n t s . B y d e f a u l t t h e p a r a m e t e r s a r e m a n d a t o r y , a n d i t i s n o t p e r m i t t e d t o p a s s m o r e a r g u m e n t s t h a n e x p e c t e d . S o t h e a b o v e i s e q u i v a l e n t t o
sub foo {
die "Too many arguments for subroutine" unless @_ <= 2;
die "Too few arguments for subroutine" unless @_ >= 2;
my $left = $_[0];
my $right = $_[1 ];
return $left + $right;
}
A n a r g u m e n t c a n b e i g n o r e d b y o m i t t i n g t h e m a i n p a r t o f t h e n a m e f r o m a p a r a m e t e r d e c l a r a t i o n , l e a v i n g j u s t a b a r e $
s i g i l . F o r e x a m p l e ,
sub foo ($first, $, $third) {
return "first=$first, third=$third";
}
A l t h o u g h t h e i g n o r e d a r g u m e n t d o e s n ' t g o i n t o a v a r i a b l e , i t i s s t i l l m a n d a t o r y f o r t h e c a l l e r t o p a s s i t .
A p o s i t i o n a l p a r a m e t e r i s m a d e o p t i o n a l b y g i v i n g a d e f a u l t v a l u e , s e p a r a t e d f r o m t h e p a r a m e t e r n a m e b y =
:
sub foo ($left, $right = 0) {
return $left + $right;
}
T h e a b o v e s u b r o u t i n e m a y b e c a l l e d w i t h e i t h e r o n e o r t w o a r g u m e n t s . T h e d e f a u l t v a l u e e x p r e s s i o n i s e v a l u a t e d w h e n t h e s u b r o u t i n e i s c a l l e d , s o i t m a y p r o v i d e d i f f e r e n t d e f a u l t v a l u e s f o r d i f f e r e n t c a l l s . I t i s o n l y e v a l u a t e d i f t h e a r g u m e n t w a s a c t u a l l y o m i t t e d f r o m t h e c a l l . F o r e x a m p l e ,
my $auto_id = 0;
sub foo ($thing, $id = $auto_id++) {
print "$thing has ID $id";
}
a u t o m a t i c a l l y a s s i g n s d i s t i n c t s e q u e n t i a l I D s t o t h i n g s f o r w h i c h n o I D w a s s u p p l i e d b y t h e c a l l e r . A d e f a u l t v a l u e e x p r e s s i o n m a y a l s o r e f e r t o p a r a m e t e r s e a r l i e r i n t h e s i g n a t u r e , m a k i n g t h e d e f a u l t f o r o n e p a r a m e t e r v a r y a c c o r d i n g t o t h e e a r l i e r p a r a m e t e r s . F o r e x a m p l e ,
sub foo ($first_name, $surname, $nickname = $first_name) {
print "$first_name $surname is known as \"$nickname\"";
}
A d e f a u l t v a l u e e x p r e s s i o n c a n a l s o b e w r i t t e n u s i n g t h e / / =
o p e r a t o r , w h e r e i t w i l l b e e v a l u a t e d a n d u s e d i f t h e c a l l e r o m i t t e d a v a l u e o r t h e v a l u e p r o v i d e d w a s u n d e f
.
sub foo ($name //= "world") {
print "Hello, $name";
}
foo(undef); # will print "Hello, world"
S i m i l a r l y , t h e | | =
o p e r a t o r c a n b e u s e d t o p r o v i d e a d e f a u l t e x p r e s s i o n t o b e u s e d w h e n e v e r t h e c a l l e r p r o v i d e d a f a l s e v a l u e ( a n d r e m e m b e r t h a t a m i s s i n g o r u n
d e f
v a l u e a r e a l s o f a l s e ) .
sub foo ($x ||= 10) {
return 5 + $x;
}
A n o p t i o n a l p a r a m e t e r c a n b e n a m e l e s s j u s t l i k e a m a n d a t o r y p a r a m e t e r . F o r e x a m p l e ,
sub foo ($thing, $ = 1) {
print $thing;
}
T h e p a r a m e t e r ' s d e f a u l t v a l u e w i l l s t i l l b e e v a l u a t e d i f t h e c o r r e s p o n d i n g a r g u m e n t i s n ' t s u p p l i e d , e v e n t h o u g h t h e v a l u e w o n ' t b e s t o r e d a n y w h e r e . T h i s i s i n c a s e e v a l u a t i n g i t h a s i m p o r t a n t s i d e e f f e c t s . H o w e v e r , i t w i l l b e e v a l u a t e d i n v o i d c o n t e x t , s o i f i t d o e s n ' t h a v e s i d e e f f e c t s a n d i s n o t t r i v i a l i t w i l l g e n e r a t e a w a r n i n g i f t h e " v o i d " w a r n i n g c a t e g o r y i s e n a b l e d . I f a n a m e l e s s o p t i o n a l p a r a m e t e r ' s d e f a u l t v a l u e i s n o t i m p o r t a n t , i t m a y b e o m i t t e d j u s t a s t h e p a r a m e t e r ' s n a m e w a s :
sub foo ($thing, $=) {
print $thing;
}
O p t i o n a l p o s i t i o n a l p a r a m e t e r s m u s t c o m e a f t e r a l l m a n d a t o r y p o s i t i o n a l p a r a m e t e r s . ( I f t h e r e a r e n o m a n d a t o r y p o s i t i o n a l p a r a m e t e r s t h e n a n o p t i o n a l p o s i t i o n a l p a r a m e t e r s c a n b e t h e f i r s t t h i n g i n t h e s i g n a t u r e . ) I f t h e r e a r e m u l t i p l e o p t i o n a l p o s i t i o n a l p a r a m e t e r s a n d n o t e n o u g h a r g u m e n t s a r e s u p p l i e d t o f i l l t h e m a l l , t h e y w i l l b e f i l l e d f r o m l e f t t o r i g h t .
A f t e r p o s i t i o n a l p a r a m e t e r s , a d d i t i o n a l a r g u m e n t s m a y b e c a p t u r e d i n a s l u r p y p a r a m e t e r . T h e s i m p l e s t f o r m o f t h i s i s j u s t a n a r r a y v a r i a b l e :
sub foo ($filter, @inputs) {
print $filter->($_) foreach @inputs;
}
W i t h a s l u r p y p a r a m e t e r i n t h e s i g n a t u r e , t h e r e i s n o u p p e r l i m i t o n h o w m a n y a r g u m e n t s m a y b e p a s s e d . A s l u r p y a r r a y p a r a m e t e r m a y b e n a m e l e s s j u s t l i k e a p o s i t i o n a l p a r a m e t e r , i n w h i c h c a s e i t s o n l y e f f e c t i s t o t u r n o f f t h e a r g u m e n t l i m i t t h a t w o u l d o t h e r w i s e a p p l y :
sub foo ($thing, @) {
print $thing;
}
A s l u r p y p a r a m e t e r m a y i n s t e a d b e a h a s h , i n w h i c h c a s e t h e a r g u m e n t s a v a i l a b l e t o i t a r e i n t e r p r e t e d a s a l t e r n a t i n g k e y s a n d v a l u e s . T h e r e m u s t b e a s m a n y k e y s a s v a l u e s : i f t h e r e i s a n o d d a r g u m e n t t h e n a n e x c e p t i o n w i l l b e t h r o w n . K e y s w i l l b e s t r i n g i f i e d , a n d i f t h e r e a r e d u p l i c a t e s t h e n t h e l a t e r i n s t a n c e t a k e s p r e c e d e n c e o v e r t h e e a r l i e r , a s w i t h s t a n d a r d h a s h c o n s t r u c t i o n .
sub foo ($filter, %inputs) {
print $filter->($_, $inputs{$_}) foreach sort keys %inputs;
}
A s l u r p y h a s h p a r a m e t e r m a y b e n a m e l e s s j u s t l i k e o t h e r k i n d s o f p a r a m e t e r . I t s t i l l i n s i s t s t h a t t h e n u m b e r o f a r g u m e n t s a v a i l a b l e t o i t b e e v e n , e v e n t h o u g h t h e y ' r e n o t b e i n g p u t i n t o a v a r i a b l e .
sub foo ($thing, %) {
print $thing;
}
A s l u r p y p a r a m e t e r , e i t h e r a r r a y o r h a s h , m u s t b e t h e l a s t t h i n g i n t h e s i g n a t u r e . I t m a y f o l l o w m a n d a t o r y a n d o p t i o n a l p o s i t i o n a l p a r a m e t e r s ; i t m a y a l s o b e t h e o n l y t h i n g i n t h e s i g n a t u r e . S l u r p y p a r a m e t e r s c a n n o t h a v e d e f a u l t v a l u e s : i f n o a r g u m e n t s a r e s u p p l i e d f o r t h e m t h e n y o u g e t a n e m p t y a r r a y o r e m p t y h a s h .
A s i g n a t u r e m a y b e e n t i r e l y e m p t y , i n w h i c h c a s e a l l i t d o e s i s c h e c k t h a t t h e c a l l e r p a s s e d n o a r g u m e n t s :
sub foo () {
return 123;
}
P r i o r t o P e r l 5 . 3 6 t h e s e w e r e c o n s i d e r e d e x p e r i m e n t a l , a n d e m i t t e d a w a r n i n g i n t h e e x p e r i m e n t a l
: : s i g n a t u r e s
c a t e g o r y . F r o m P e r l 5 . 3 6 o n w a r d s t h i s n o l o n g e r h a p p e n s , t h o u g h t h e w a r n i n g c a t e g o r y s t i l l e x i s t s f o r b a c k - c o m p a t i b i l i t y w i t h c o d e t h a t a t t e m p t s t o d i s a b l e i t w i t h a s t a t e m e n t s u c h a s :
no warnings 'experimental::signatures';
I n t h e c u r r e n t P e r l i m p l e m e n t a t i o n , w h e n u s i n g a s i g n a t u r e t h e a r g u m e n t s a r e s t i l l a l s o a v a i l a b l e i n t h e s p e c i a l a r r a y v a r i a b l e @ _
. H o w e v e r , a c c e s s i n g t h e m v i a t h i s a r r a y i s n o w d i s c o u r a g e d , a n d s h o u l d n o t b e r e l i e d u p o n i n n e w l y - w r i t t e n c o d e a s t h i s a b i l i t y m a y c h a n g e i n a f u t u r e v e r s i o n . C o d e t h a t a t t e m p t s t o a c c e s s t h e @ _
a r r a y w i l l p r o d u c e w a r n i n g s i n t h e e x p e r i m e n t a l : : a r g s _ a r r
a y _ w i t h _ s i g n a t u r e s
c a t e g o r y w h e n c o m p i l e d :
sub f ($x) {
# This line emits the warning seen below
print "Arguments are @_";
}
Use of @_ in join or string with signatured subroutine is
experimental at ...
T h e r e i s a d i f f e r e n c e b e t w e e n t h e t w o w a y s o f a c c e s s i n g t h e a r g u m e n t s : @ _
a l i a s e s t h e a r g u m e n t s , b u t t h e s i g n a t u r e v a r i a b l e s g e t c o p i e s o f t h e a r g u m e n t s . S o w r i t i n g t o a s i g n a t u r e v a r i a b l e o n l y c h a n g e s t h a t v a r i a b l e , a n d h a s n o e f f e c t o n t h e c a l l e r ' s v a r i a b l e s , b u t w r i t i n g t o a n e l e m e n t o f @ _
m o d i f i e s w h a t e v e r t h e c a l l e r u s e d t o s u p p l y t h a t a r g u m e n t .
T h e r e i s a p o t e n t i a l s y n t a c t i c a m b i g u i t y b e t w e e n s i g n a t u r e s a n d p r o t o t y p e s ( s e e " P r o t o t y p e s " ) , b e c a u s e b o t h s t a r t w i t h a n o p e n i n g p a r e n t h e s i s a n d b o t h c a n a p p e a r i n s o m e o f t h e s a m e p l a c e s , s u c h a s j u s t a f t e r t h e n a m e i n a s u b r o u t i n e d e c l a r a t i o n . F o r h i s t o r i c a l r e a s o n s , w h e n s i g n a t u r e s a r e n o t e n a b l e d , a n y o p e n i n g p a r e n t h e s i s i n s u c h a c o n t e x t w i l l t r i g g e r v e r y f o r g i v i n g p r o t o t y p e p a r s i n g . M o s t s i g n a t u r e s w i l l b e i n t e r p r e t e d a s p r o t o t y p e s i n t h o s e c i r c u m s t a n c e s , b u t w o n ' t b e v a l i d p r o t o t y p e s . ( A v a l i d p r o t o t y p e c a n n o t c o n t a i n a n y a l p h a b e t i c c h a r a c t e r . ) T h i s w i l l l e a d t o s o m e w h a t c o n f u s i n g e r r o r m e s s a g e s .
T o a v o i d a m b i g u i t y , w h e n s i g n a t u r e s a r e e n a b l e d t h e s p e c i a l s y n t a x f o r p r o t o t y p e s i s d i s a b l e d . T h e r e i s n o a t t e m p t t o g u e s s w h e t h e r a p a r e n t h e s i s e d g r o u p w a s i n t e n d e d t o b e a p r o t o t y p e o r a s i g n a t u r e . T o g i v e a s u b r o u t i n e a p r o t o t y p e u n d e r t h e s e c i r c u m s t a n c e s , u s e a p r o t o t y p e a t t r i b u t e . F o r e x a m p l e ,
sub foo :prototype($) { $_[0] }
I t i s e n t i r e l y p o s s i b l e f o r a s u b r o u t i n e t o h a v e b o t h a p r o t o t y p e a n d a s i g n a t u r e . T h e y d o d i f f e r e n t j o b s : t h e p r o t o t y p e a f f e c t s c o m p i l a t i o n o f c a l l s t o t h e s u b r o u t i n e , a n d t h e s i g n a t u r e p u t s a r g u m e n t v a l u e s i n t o l e x i c a l v a r i a b l e s a t r u n t i m e . Y o u c a n t h e r e f o r e w r i t e
sub foo :prototype($$) ($left, $right) {
return $left + $right;
}
T h e p r o t o t y p e a t t r i b u t e , a n d a n y o t h e r a t t r i b u t e s , m u s t c o m e b e f o r e t h e s i g n a t u r e . T h e s i g n a t u r e a l w a y s i m m e d i a t e l y p r e c e d e s t h e b l o c k o f t h e s u b r o u t i n e ' s b o d y .
# P r i v a t e V a r i a b l e s v i a m y ( )
S y n o p s i s :
my $foo; # declare $foo lexically local
my (@wid, %get); # declare list of variables local
my $foo = "flurp"; # declare $foo lexical, and init it
my @oof = @bar; # declare @oof lexical, and init it
my $x : Foo = $y; # similar, with an attribute applied
W A R N I N G : T h e u s e o f a t t r i b u t e l i s t s o n my
d e c l a r a t i o n s i s s t i l l e v o l v i n g . T h e c u r r e n t s e m a n t i c s a n d i n t e r f a c e a r e s u b j e c t t o c h a n g e . S e e a t t r i b u t e s a n d A t t r i b u t e : : H a n d l e r s .
T h e my
o p e r a t o r d e c l a r e s t h e l i s t e d v a r i a b l e s t o b e l e x i c a l l y c o n f i n e d t o t h e e n c l o s i n g b l o c k , c o n d i t i o n a l ( if
/ u n l e s s
/ e l s i f
/ e l s e
) , l o o p ( f o r
/ f o r e a c h
/ w h i l e
/ u n t i l
/ c o
n t i n u e
) , s u b r o u t i n e , e v a l
, o r do
/ r e q u i r e
/ u s e
' d f i l e . I f m o r e t h a n o n e v a l u e i s l i s t e d , t h e l i s t m u s t b e p l a c e d i n p a r e n t h e s e s . A l l l i s t e d e l e m e n t s m u s t b e l e g a l l v a l u e s . O n l y a l p h a n u m e r i c i d e n t i f i e r s m a y b e l e x i c a l l y s c o p e d - - m a g i c a l b u i l t - i n s l i k e $ /
m u s t c u r r e n t l y b e l o c a l
i z e d w i t h l o c a l
i n s t e a d t o l i m i t t h e i r s c o p e d y n a m i c a l l y .
U n l i k e g l o b a l o r p a c k a g e v a r i a b l e s l o c a l i z e d b y t h e l o c a l
o p e r a t o r , l e x i c a l v a r i a b l e s d e c l a r e d w i t h my
a r e t o t a l l y h i d d e n f r o m t h e o u t s i d e w o r l d , i n c l u d i n g a n y c a l l e d s u b r o u t i n e s . T h i s i s t r u e i f i t ' s t h e s a m e s u b r o u t i n e c a l l e d f r o m i t s e l f o r e l s e w h e r e - - e v e r y c a l l g e t s i t s o w n c o p y .
T h i s d o e s n ' t m e a n t h a t a my
v a r i a b l e d e c l a r e d i n a s t a t i c a l l y e n c l o s i n g l e x i c a l s c o p e w o u l d b e i n v i s i b l e . O n l y d y n a m i c s c o p e s a r e c u t o f f . F o r e x a m p l e , t h e b u m p x ( )
f u n c t i o n b e l o w h a s a c c e s s t o t h e l e x i c a l $ x v a r i a b l e b e c a u s e b o t h t h e my
a n d t h e s u b
o c c u r r e d a t t h e s a m e s c o p e , p r e s u m a b l y f i l e s c o p e .
my $x = 10;
sub bumpx { $x++ }
An e v a l ( )
, h o w e v e r , c a n s e e l e x i c a l v a r i a b l e s o f t h e s c o p e i t i s b e i n g e v a l u a t e d i n , s o l o n g a s t h e n a m e s a r e n ' t h i d d e n b y d e c l a r a t i o n s w i t h i n t h e e v a l ( )
i t s e l f . S e e p e r l r e f .
T h e p a r a m e t e r l i s t t o m y ( ) m a y b e a s s i g n e d t o i f d e s i r e d , w h i c h a l l o w s y o u t o i n i t i a l i z e y o u r v a r i a b l e s . ( I f n o i n i t i a l i z e r i s g i v e n f o r a p a r t i c u l a r v a r i a b l e , i t i s c r e a t e d w i t h t h e u n d e f i n e d v a l u e . ) C o m m o n l y t h i s i s u s e d t o n a m e i n p u t p a r a m e t e r s t o a s u b r o u t i n e . E x a m p l e s :
$arg = "fred"; # "global" variable
$n = cube_root(27 );
print "$arg thinks the root is $n\n";
# outputs: fred thinks the root is 3
sub cube_root {
my $arg = shift; # name doesn't matter
$arg **= 1/3;
return $arg;
}
T h e my
i s s i m p l y a m o d i f i e r o n s o m e t h i n g y o u m i g h t a s s i g n t o . S o w h e n y o u d o a s s i g n t o v a r i a b l e s i n i t s a r g u m e n t l i s t , my
d o e s n ' t c h a n g e w h e t h e r t h o s e v a r i a b l e s a r e v i e w e d a s a s c a l a r o r a n a r r a y . S o
my ($foo) = <STDIN>; # WRONG?
my @FOO = <STDIN>;
b o t h s u p p l y a l i s t c o n t e x t t o t h e r i g h t - h a n d s i d e , w h i l e
my $foo = <STDIN>;
s u p p l i e s a s c a l a r c o n t e x t . B u t t h e f o l l o w i n g d e c l a r e s o n l y o n e v a r i a b l e :
my $foo, $bar = 1; # WRONG
T h a t h a s t h e s a m e e f f e c t a s
my $foo;
$bar = 1;
T h e d e c l a r e d v a r i a b l e i s n o t i n t r o d u c e d ( i s n o t v i s i b l e ) u n t i l a f t e r t h e c u r r e n t s t a t e m e n t . T h u s ,
my $x = $x;
c a n b e u s e d t o i n i t i a l i z e a n e w $ x w i t h t h e v a l u e o f t h e o l d $ x , a n d t h e e x p r e s s i o n
my $x = 123 and $x == 123
i s f a l s e u n l e s s t h e o l d $ x h a p p e n e d t o h a v e t h e v a l u e 1 2 3
.
L e x i c a l s c o p e s o f c o n t r o l s t r u c t u r e s a r e n o t b o u n d e d p r e c i s e l y b y t h e b r a c e s t h a t d e l i m i t t h e i r c o n t r o l l e d b l o c k s ; c o n t r o l e x p r e s s i o n s a r e p a r t o f t h a t s c o p e , t o o . T h u s i n t h e l o o p
while (my $line = <>) {
$line = lc $line;
} continue {
print $line;
}
t h e s c o p e o f $ l i n e e x t e n d s f r o m i t s d e c l a r a t i o n t h r o u g h o u t t h e r e s t o f t h e l o o p c o n s t r u c t ( i n c l u d i n g t h e c o n t i n u e
c l a u s e ) , b u t n o t b e y o n d i t . S i m i l a r l y , i n t h e c o n d i t i o n a l
if ((my $answer = <STDIN>) =~ /^yes$/i) {
user_agrees();
} elsif ($answer =~ /^no$/i) {
user_disagrees();
} else {
chomp $answer;
die "'$answer' is neither 'yes' nor 'no'";
}
t h e s c o p e o f $ a n s w e r e x t e n d s f r o m i t s d e c l a r a t i o n t h r o u g h t h e r e s t o f t h a t c o n d i t i o n a l , i n c l u d i n g a n y e l s i f
a n d e l s e
c l a u s e s , b u t n o t b e y o n d i t . S e e " S i m p l e S t a t e m e n t s " i n p e r l s y n f o r i n f o r m a t i o n o n t h e s c o p e o f v a r i a b l e s i n s t a t e m e n t s w i t h m o d i f i e r s .
T h e f o r e a c h
l o o p d e f a u l t s t o s c o p i n g i t s i n d e x v a r i a b l e d y n a m i c a l l y i n t h e m a n n e r o f l o c a l
. H o w e v e r , i f t h e i n d e x v a r i a b l e i s p r e f i x e d w i t h t h e k e y w o r d my
, o r i f t h e r e i s a l r e a d y a l e x i c a l b y t h a t n a m e i n s c o p e , t h e n a n e w l e x i c a l i s c r e a t e d i n s t e a d . T h u s i n t h e l o o p
for my $i (1, 2, 3) {
some_function();
}
t h e s c o p e o f $ i e x t e n d s t o t h e e n d o f t h e l o o p , b u t n o t b e y o n d i t , r e n d e r i n g t h e v a l u e o f $ i i n a c c e s s i b l e w i t h i n s o m e _ f u n c t i o n ( )
.
S o m e u s e r s m a y w i s h t o e n c o u r a g e t h e u s e o f l e x i c a l l y s c o p e d v a r i a b l e s . A s a n a i d t o c a t c h i n g i m p l i c i t u s e s t o p a c k a g e v a r i a b l e s , w h i c h a r e a l w a y s g l o b a l , i f y o u s a y
use strict 'vars';
t h e n a n y v a r i a b l e m e n t i o n e d f r o m t h e r e t o t h e e n d o f t h e e n c l o s i n g b l o c k m u s t e i t h e r r e f e r t o a l e x i c a l v a r i a b l e , b e p r e d e c l a r e d v i a o u r
or u s e v a r s
, o r e l s e m u s t b e f u l l y q u a l i f i e d w i t h t h e p a c k a g e n a m e . A c o m p i l a t i o n e r r o r r e s u l t s o t h e r w i s e . A n i n n e r b l o c k m a y c o u n t e r m a n d t h i s w i t h n o s t r
i c t ' v a r s '
.
A my
h a s b o t h a c o m p i l e - t i m e a n d a r u n - t i m e e f f e c t . A t c o m p i l e t i m e , t h e c o m p i l e r t a k e s n o t i c e o f i t . T h e p r i n c i p a l u s e f u l n e s s o f t h i s i s t o q u i e t u s e s t r i c t ' v a r
s '
, b u t i t i s a l s o e s s e n t i a l f o r g e n e r a t i o n o f c l o s u r e s a s d e t a i l e d i n p e r l r e f . A c t u a l i n i t i a l i z a t i o n i s d e l a y e d u n t i l r u n t i m e , t h o u g h , s o i t g e t s e x e c u t e d a t t h e a p p r o p r i a t e t i m e , s u c h a s e a c h t i m e t h r o u g h a l o o p , f o r e x a m p l e .
V a r i a b l e s d e c l a r e d w i t h my
a r e n o t p a r t o f a n y p a c k a g e a n d a r e t h e r e f o r e n e v e r f u l l y q u a l i f i e d w i t h t h e p a c k a g e n a m e . I n p a r t i c u l a r , y o u ' r e n o t a l l o w e d t o t r y t o m a k e a p a c k a g e v a r i a b l e ( o r o t h e r g l o b a l ) l e x i c a l :
my $pack::var; # ERROR! Illegal syntax
I n f a c t , a p a c k a g e o r g l o b a l v a r i a b l e i s s t i l l a c c e s s i b l e u s i n g t h e f u l l y q u a l i f i e d : :
n o t a t i o n e v e n w h i l e a l e x i c a l o f t h e s a m e n a m e i s a l s o v i s i b l e :
package main;
our $x = 10;
my $x = 20;
print "$x and $::x\n";
T h a t w i l l p r i n t o u t 20
a n d 10
.
Y o u m a y d e c l a r e my
v a r i a b l e s a t t h e o u t e r m o s t s c o p e o f a f i l e t o h i d e a n y s u c h i d e n t i f i e r s f r o m t h e w o r l d o u t s i d e t h a t f i l e . T h i s i s s i m i l a r i n s p i r i t t o C ' s s t a t i c v a r i a b l e s w h e n t h e y a r e u s e d a t t h e f i l e l e v e l . T o d o t h i s w i t h a s u b r o u t i n e r e q u i r e s t h e u s e o f a c l o s u r e ( a n a n o n y m o u s f u n c t i o n t h a t a c c e s s e s e n c l o s i n g l e x i c a l s ) . I f y o u w a n t t o c r e a t e a p r i v a t e s u b r o u t i n e t h a t c a n n o t b e c a l l e d f r o m o u t s i d e t h a t b l o c k , i t c a n d e c l a r e a l e x i c a l v a r i a b l e c o n t a i n i n g a n a n o n y m o u s s u b r e f e r e n c e :
my $secret_version = '1.001-beta';
my $secret_sub = sub { print $secret_version };
$secret_sub->();
A s l o n g a s t h e r e f e r e n c e i s n e v e r r e t u r n e d b y a n y f u n c t i o n w i t h i n t h e m o d u l e , n o o u t s i d e m o d u l e c a n s e e t h e s u b r o u t i n e , b e c a u s e i t s n a m e i s n o t i n a n y p a c k a g e ' s s y m b o l t a b l e . R e m e m b e r t h a t i t ' s n o t R E A L L Y c a l l e d $ s o m e _ p a c k : :
s e c r e t _ v e r s i o n
o r a n y t h i n g ; i t ' s j u s t $ s e c r e t _ v e r s i o n , u n q u a l i f i e d a n d u n q u a l i f i a b l e .
T h i s d o e s n o t w o r k w i t h o b j e c t m e t h o d s , h o w e v e r ; a l l o b j e c t m e t h o d s h a v e t o b e i n t h e s y m b o l t a b l e o f s o m e p a c k a g e t o b e f o u n d . S e e " F u n c t i o n T e m p l a t e s " i n p e r l r e f f o r s o m e t h i n g o f a w o r k - a r o u n d t o t h i s .
# P e r s i s t e n t P r i v a t e V a r i a b l e s
T h e r e a r e t w o w a y s t o b u i l d p e r s i s t e n t p r i v a t e v a r i a b l e s i n P e r l 5 . 1 0 . F i r s t , y o u c a n s i m p l y u s e t h e s t a t e
f e a t u r e . O r , y o u c a n u s e c l o s u r e s , i f y o u w a n t t o s t a y c o m p a t i b l e w i t h r e l e a s e s o l d e r t h a n 5 . 1 0 .
# P e r s i s t e n t v a r i a b l e s v i a s t a t e ( )
B e g i n n i n g w i t h P e r l 5 . 1 0 . 0 , y o u c a n d e c l a r e v a r i a b l e s w i t h t h e s
t a t e
k e y w o r d i n p l a c e o f my
. F o r t h a t t o w o r k , t h o u g h , y o u m u s t h a v e e n a b l e d t h a t f e a t u r e b e f o r e h a n d , e i t h e r b y u s i n g t h e f e a t u r e
p r a g m a , o r b y u s i n g - E
o n o n e - l i n e r s ( s e e f e a t u r e ) . B e g i n n i n g w i t h P e r l 5 . 1 6 , t h e C O R E : : s t a t e
f o r m d o e s n o t r e q u i r e t h e f e a t u r e
p r a g m a .
T h e s t a t e
k e y w o r d c r e a t e s a l e x i c a l v a r i a b l e ( f o l l o w i n g t h e s a m e s c o p i n g r u l e s a s my
) t h a t p e r s i s t s f r o m o n e s u b r o u t i n e c a l l t o t h e n e x t . I f a s t a t e v a r i a b l e r e s i d e s i n s i d e a n a n o n y m o u s s u b r o u t i n e , t h e n e a c h c o p y o f t h e s u b r o u t i n e h a s i t s o w n c o p y o f t h e s t a t e v a r i a b l e . H o w e v e r , t h e v a l u e o f t h e s t a t e v a r i a b l e w i l l s t i l l p e r s i s t b e t w e e n c a l l s t o t h e s a m e c o p y o f t h e a n o n y m o u s s u b r o u t i n e . ( D o n ' t f o r g e t t h a t s u b { . .
. }
c r e a t e s a n e w s u b r o u t i n e e a c h t i m e i t i s e x e c u t e d . )
F o r e x a m p l e , t h e f o l l o w i n g c o d e m a i n t a i n s a p r i v a t e c o u n t e r , i n c r e m e n t e d e a c h t i m e t h e g i m m e _ a n o t h e r ( ) f u n c t i o n i s c a l l e d :
use feature 'state';
sub gimme_another { state $x; return ++$x }
A n d t h i s e x a m p l e u s e s a n o n y m o u s s u b r o u t i n e s t o c r e a t e s e p a r a t e c o u n t e r s :
use feature 'state';
sub create_counter {
return sub { state $x; return ++$x }
}
A l s o , s i n c e $ x
i s l e x i c a l , i t c a n ' t b e r e a c h e d o r m o d i f i e d b y a n y P e r l c o d e o u t s i d e .
W h e n c o m b i n e d w i t h v a r i a b l e d e c l a r a t i o n , s i m p l e a s s i g n m e n t t o s t
a t e
v a r i a b l e s ( a s i n s t a t e $ x =
4 2
) i s e x e c u t e d o n l y t h e f i r s t t i m e . W h e n s u c h s t a t e m e n t s a r e e v a l u a t e d s u b s e q u e n t t i m e s , t h e a s s i g n m e n t i s i g n o r e d . T h e b e h a v i o r o f a s s i g n m e n t t o s t a t e
d e c l a r a t i o n s w h e r e t h e l e f t h a n d s i d e o f t h e a s s i g n m e n t i n v o l v e s a n y p a r e n t h e s e s i s c u r r e n t l y u n d e f i n e d .
# P e r s i s t e n t v a r i a b l e s w i t h c l o s u r e s
J u s t b e c a u s e a l e x i c a l v a r i a b l e i s l e x i c a l l y ( a l s o c a l l e d s t a t i c a l l y ) s c o p e d t o i t s e n c l o s i n g b l o c k , e v a l
, o r do
F I L E , t h i s d o e s n ' t m e a n t h a t w i t h i n a f u n c t i o n i t w o r k s l i k e a C s t a t i c . I t n o r m a l l y w o r k s m o r e l i k e a C a u t o , b u t w i t h i m p l i c i t g a r b a g e c o l l e c t i o n .
U n l i k e l o c a l v a r i a b l e s i n C o r C + + , P e r l ' s l e x i c a l v a r i a b l e s d o n ' t n e c e s s a r i l y g e t r e c y c l e d j u s t b e c a u s e t h e i r s c o p e h a s e x i t e d . I f s o m e t h i n g m o r e p e r m a n e n t i s s t i l l a w a r e o f t h e l e x i c a l , i t w i l l s t i c k a r o u n d . S o l o n g a s s o m e t h i n g e l s e r e f e r e n c e s a l e x i c a l , t h a t l e x i c a l w o n ' t b e f r e e d - - w h i c h i s a s i t s h o u l d b e . Y o u w o u l d n ' t w a n t m e m o r y b e i n g f r e e u n t i l y o u w e r e d o n e u s i n g i t , o r k e p t a r o u n d o n c e y o u w e r e d o n e . A u t o m a t i c g a r b a g e c o l l e c t i o n t a k e s c a r e o f t h i s f o r y o u .
T h i s m e a n s t h a t y o u c a n p a s s b a c k o r s a v e a w a y r e f e r e n c e s t o l e x i c a l v a r i a b l e s , w h e r e a s t o r e t u r n a p o i n t e r t o a C a u t o i s a g r a v e e r r o r . I t a l s o g i v e s u s a w a y t o s i m u l a t e C ' s f u n c t i o n s t a t i c s . H e r e ' s a m e c h a n i s m f o r g i v i n g a f u n c t i o n p r i v a t e v a r i a b l e s w i t h b o t h l e x i c a l s c o p i n g a n d a s t a t i c l i f e t i m e . I f y o u d o w a n t t o c r e a t e s o m e t h i n g l i k e C ' s s t a t i c v a r i a b l e s , j u s t e n c l o s e t h e w h o l e f u n c t i o n i n a n e x t r a b l o c k , a n d p u t t h e s t a t i c v a r i a b l e o u t s i d e t h e f u n c t i o n b u t i n t h e b l o c k .
{
my $secret_val = 0;
sub gimme_another {
return ++$secret_val;
}
}
# $secret_val now becomes unreachable by the outside
# world, but retains its value between calls to gimme_another
I f t h i s f u n c t i o n i s b e i n g s o u r c e d i n f r o m a s e p a r a t e f i l e v i a r e
q u i r e
or u s e
, t h e n t h i s i s p r o b a b l y j u s t f i n e . I f i t ' s a l l i n t h e m a i n p r o g r a m , y o u ' l l n e e d t o a r r a n g e f o r t h e my
t o b e e x e c u t e d e a r l y , e i t h e r b y p u t t i n g t h e w h o l e b l o c k a b o v e y o u r m a i n p r o g r a m , o r m o r e l i k e l y , p l a c i n g m e r e l y a B
E G I N
c o d e b l o c k a r o u n d i t t o m a k e s u r e i t g e t s e x e c u t e d b e f o r e y o u r p r o g r a m s t a r t s t o r u n :
BEGIN {
my $secret_val = 0;
sub gimme_another {
return ++$secret_val;
}
}
S e e " B E G I N , U N I T C H E C K , C H E C K , I N I T a n d E N D " i n p e r l m o d a b o u t t h e s p e c i a l t r i g g e r e d c o d e b l o c k s , B E G I N
, U N I T C H E C K
, C H E C K
, I N I T
a n d E N D
.
I f d e c l a r e d a t t h e o u t e r m o s t s c o p e ( t h e f i l e s c o p e ) , t h e n l e x i c a l s w o r k s o m e w h a t l i k e C ' s f i l e s t a t i c s . T h e y a r e a v a i l a b l e t o a l l f u n c t i o n s i n t h a t s a m e f i l e d e c l a r e d b e l o w t h e m , b u t a r e i n a c c e s s i b l e f r o m o u t s i d e t h a t f i l e . T h i s s t r a t e g y i s s o m e t i m e s u s e d i n m o d u l e s t o c r e a t e p r i v a t e v a r i a b l e s t h a t t h e w h o l e m o d u l e c a n s e e .
# T e m p o r a r y V a l u e s v i a l o c a l ( )
W A R N I N G : I n g e n e r a l , y o u s h o u l d b e u s i n g my
i n s t e a d o f l o c a l
, b e c a u s e i t ' s f a s t e r a n d s a f e r . E x c e p t i o n s t o t h i s i n c l u d e t h e g l o b a l p u n c t u a t i o n v a r i a b l e s , g l o b a l f i l e h a n d l e s a n d f o r m a t s , a n d d i r e c t m a n i p u l a t i o n o f t h e P e r l s y m b o l t a b l e i t s e l f . l o c a l
i s m o s t l y u s e d w h e n t h e c u r r e n t v a l u e o f a v a r i a b l e m u s t b e v i s i b l e t o c a l l e d s u b r o u t i n e s .
S y n o p s i s :
# localization of values
local $foo; # make $foo dynamically local
local (@wid, %get); # make list of variables local
local $foo = "flurp"; # make $foo dynamic, and init it
local @oof = @bar; # make @oof dynamic, and init it
local $hash{key} = "val"; # sets a local value for this hash entry
delete local $hash{key}; # delete this entry for the current block
local ($cond ? $v1 : $v2); # several types of lvalues support
# localization
# localization of symbols
local *FH; # localize $FH, @FH, %FH, &FH ...
local *merlyn = *randal; # now $merlyn is really $randal, plus
# @merlyn is really @randal, etc
local *merlyn = 'randal'; # SAME THING: promote 'randal' to *randal
local *merlyn = \$randal; # just alias $merlyn, not @merlyn etc
A l o c a l
m o d i f i e s i t s l i s t e d v a r i a b l e s t o b e " l o c a l " t o t h e e n c l o s i n g b l o c k , e v a l
, o r d o F I L E
- - a n d t o a n y s u b r o u t i n e c a l l e d f r o m w i t h i n t h a t b l o c k . A l o c a l
j u s t g i v e s t e m p o r a r y v a l u e s t o g l o b a l ( m e a n i n g p a c k a g e ) v a r i a b l e s . I t d o e s n o t c r e a t e a l o c a l v a r i a b l e . T h i s i s k n o w n a s d y n a m i c s c o p i n g . L e x i c a l s c o p i n g i s d o n e w i t h my
, w h i c h w o r k s m o r e l i k e C ' s a u t o d e c l a r a t i o n s .
S o m e t y p e s o f l v a l u e s c a n b e l o c a l i z e d a s w e l l : h a s h a n d a r r a y e l e m e n t s a n d s l i c e s , c o n d i t i o n a l s ( p r o v i d e d t h a t t h e i r r e s u l t i s a l w a y s l o c a l i z a b l e ) , a n d s y m b o l i c r e f e r e n c e s . A s f o r s i m p l e v a r i a b l e s , t h i s c r e a t e s n e w , d y n a m i c a l l y s c o p e d v a l u e s .
I f m o r e t h a n o n e v a r i a b l e o r e x p r e s s i o n i s g i v e n t o l o c a l
, t h e y m u s t b e p l a c e d i n p a r e n t h e s e s . T h i s o p e r a t o r w o r k s b y s a v i n g t h e c u r r e n t v a l u e s o f t h o s e v a r i a b l e s i n i t s a r g u m e n t l i s t o n a h i d d e n s t a c k a n d r e s t o r i n g t h e m u p o n e x i t i n g t h e b l o c k , s u b r o u t i n e , o r e v a l . T h i s m e a n s t h a t c a l l e d s u b r o u t i n e s c a n a l s o r e f e r e n c e t h e l o c a l v a r i a b l e , b u t n o t t h e g l o b a l o n e . T h e a r g u m e n t l i s t m a y b e a s s i g n e d t o i f d e s i r e d , w h i c h a l l o w s y o u t o i n i t i a l i z e y o u r l o c a l v a r i a b l e s . ( I f n o i n i t i a l i z e r i s g i v e n f o r a p a r t i c u l a r v a r i a b l e , i t i s c r e a t e d w i t h a n u n d e f i n e d v a l u e . )
B e c a u s e l o c a l
i s a r u n - t i m e o p e r a t o r , i t g e t s e x e c u t e d e a c h t i m e t h r o u g h a l o o p . C o n s e q u e n t l y , i t ' s m o r e e f f i c i e n t t o l o c a l i z e y o u r v a r i a b l e s o u t s i d e t h e l o o p .
# G r a m m a t i c a l n o t e o n l o c a l ( )
A l o c a l
i s s i m p l y a m o d i f i e r o n a n l v a l u e e x p r e s s i o n . W h e n y o u a s s i g n t o a l o c a l
i z e d v a r i a b l e , t h e l o c a l
d o e s n ' t c h a n g e w h e t h e r i t s l i s t i s v i e w e d a s a s c a l a r o r a n a r r a y . S o
local($foo) = <STDIN>;
local @FOO = <STDIN>;
b o t h s u p p l y a l i s t c o n t e x t t o t h e r i g h t - h a n d s i d e , w h i l e
local $foo = <STDIN>;
s u p p l i e s a s c a l a r c o n t e x t .
# L o c a l i z a t i o n o f s p e c i a l v a r i a b l e s
I f y o u l o c a l i z e a s p e c i a l v a r i a b l e , y o u ' l l b e g i v i n g a n e w v a l u e t o i t , b u t i t s m a g i c w o n ' t g o a w a y . T h a t m e a n s t h a t a l l s i d e - e f f e c t s r e l a t e d t o t h i s m a g i c s t i l l w o r k w i t h t h e l o c a l i z e d v a l u e .
T h i s f e a t u r e a l l o w s c o d e l i k e t h i s t o w o r k :
# Read the whole contents of FILE in $slurp
{ local $/ = undef; $slurp = <FILE>; }
N o t e , h o w e v e r , t h a t t h i s r e s t r i c t s l o c a l i z a t i o n o f s o m e v a l u e s ; f o r e x a m p l e , t h e f o l l o w i n g s t a t e m e n t d i e s , a s o f P e r l 5 . 1 0 . 0 , w i t h a n e r r o r M o d i f i c a t i o n o f a r e a d - o n l y v a l u e a t t e m p t e d , b e c a u s e t h e $ 1 v a r i a b l e i s m a g i c a l a n d r e a d - o n l y :
local $1 = 2;
O n e e x c e p t i o n i s t h e d e f a u l t s c a l a r v a r i a b l e : s t a r t i n g w i t h P e r l 5 . 1 4 l o c a l ( $ _ )
w i l l a l w a y s s t r i p a l l m a g i c f r o m $ _ , t o m a k e i t p o s s i b l e t o s a f e l y r e u s e $ _ i n a s u b r o u t i n e .
W A R N I N G : L o c a l i z a t i o n o f t i e d a r r a y s a n d h a s h e s d o e s n o t c u r r e n t l y w o r k a s d e s c r i b e d . T h i s w i l l b e f i x e d i n a f u t u r e r e l e a s e o f P e r l ; i n t h e m e a n t i m e , a v o i d c o d e t h a t r e l i e s o n a n y p a r t i c u l a r b e h a v i o r o f l o c a l i s i n g t i e d a r r a y s o r h a s h e s ( l o c a l i s i n g i n d i v i d u a l e l e m e n t s i s s t i l l o k a y ) . S e e " L o c a l i s i n g T i e d A r r a y s a n d H a s h e s I s B r o k e n " i n p e r l 5 8 d e l t a f o r m o r e d e t a i l s .
# L o c a l i z a t i o n o f g l o b s
T h e c o n s t r u c t
local *name;
c r e a t e s a w h o l e n e w s y m b o l t a b l e e n t r y f o r t h e g l o b n a m e
i n t h e c u r r e n t p a c k a g e . T h a t m e a n s t h a t a l l v a r i a b l e s i n i t s g l o b s l o t ( $ n a m e , @ n a m e , % n a m e , & n a m e , a n d t h e n a m e
f i l e h a n d l e ) a r e d y n a m i c a l l y r e s e t .
T h i s i m p l i e s , a m o n g o t h e r t h i n g s , t h a t a n y m a g i c e v e n t u a l l y c a r r i e d b y t h o s e v a r i a b l e s i s l o c a l l y l o s t . I n o t h e r w o r d s , s a y i n g l o
c a l * /
w i l l n o t h a v e a n y e f f e c t o n t h e i n t e r n a l v a l u e o f t h e i n p u t r e c o r d s e p a r a t o r .
# L o c a l i z a t i o n o f e l e m e n t s o f c o m p o s i t e t y p e s
I t ' s a l s o w o r t h t a k i n g a m o m e n t t o e x p l a i n w h a t h a p p e n s w h e n y o u l o c a l
i z e a m e m b e r o f a c o m p o s i t e t y p e ( i . e . a n a r r a y o r h a s h e l e m e n t ) . I n t h i s c a s e , t h e e l e m e n t i s l o c a l
i z e d b y n a m e . T h i s m e a n s t h a t w h e n t h e s c o p e o f t h e l o
c a l ( )
e n d s , t h e s a v e d v a l u e w i l l b e r e s t o r e d t o t h e h a s h e l e m e n t w h o s e k e y w a s n a m e d i n t h e l o c a
l ( )
, o r t h e a r r a y e l e m e n t w h o s e i n d e x w a s n a m e d i n t h e l o c a l ( )
. I f t h a t e l e m e n t w a s d e l e t e d w h i l e t h e l o c a l ( )
w a s i n e f f e c t ( e . g . b y a d e l e t e ( )
f r o m a h a s h o r a s h i f t ( )
o f a n a r r a y ) , i t w i l l s p r i n g b a c k i n t o e x i s t e n c e , p o s s i b l y e x t e n d i n g a n a r r a y a n d f i l l i n g i n t h e s k i p p e d e l e m e n t s w i t h u
n d e f
. F o r i n s t a n c e , i f y o u s a y
%hash = ( 'This' => 'is', 'a' => 'test' );
@ary = ( 0..5 );
{
local($ary[5 ]) = 6;
local($hash{'a'}) = 'drill';
while (my $e = pop(@ary)) {
print "$e . . .\n";
last unless $e > 3;
}
if (@ary) {
$hash{'only a'} = 'test';
delete $hash{'a'};
}
}
print join(' ', map { "$_ $hash{$_}" } sort keys %hash),".\n";
print "The array has ",scalar(@ary)," elements: ",
join(', ', map { defined $_ ? $_ : 'undef' } @ary),"\n";
P e r l w i l l p r i n t
6 . . .
4 . . .
3 . . .
This is a test only a test.
The array has 6 elements: 0, 1, 2, undef, undef, 5
T h e b e h a v i o r o f l o c a l ( ) o n n o n - e x i s t e n t m e m b e r s o f c o m p o s i t e t y p e s i s s u b j e c t t o c h a n g e i n f u t u r e . T h e b e h a v i o r o f l o c a l ( ) o n a r r a y e l e m e n t s s p e c i f i e d u s i n g n e g a t i v e i n d e x e s i s p a r t i c u l a r l y s u r p r i s i n g , a n d i s v e r y l i k e l y t o c h a n g e .
# L o c a l i z e d d e l e t i o n o f e l e m e n t s o f c o m p o s i t e t y p e s
Y o u c a n u s e t h e d e l e t e l o c a l $ a r
r a y [ $ i d x ]
a n d d e l e t e l o c a l $ h a s h
{ k e y }
c o n s t r u c t s t o d e l e t e a c o m p o s i t e t y p e e n t r y f o r t h e c u r r e n t b l o c k a n d r e s t o r e i t w h e n i t e n d s . T h e y r e t u r n t h e a r r a y / h a s h v a l u e b e f o r e t h e l o c a l i z a t i o n , w h i c h m e a n s t h a t t h e y a r e r e s p e c t i v e l y e q u i v a l e n t t o
do {
my $val = $array[$idx];
local $array[$idx];
delete $array[$idx];
$val
}
a n d
do {
my $val = $hash{key};
local $hash{key};
delete $hash{key};
$val
}
e x c e p t t h a t f o r t h o s e t h e l o c a l
i s s c o p e d t o t h e do
b l o c k . S l i c e s a r e a l s o a c c e p t e d .
my %hash = (
a => [ 7, 8, 9 ],
b => 1,
)
{
my $x = delete local $hash{a};
# $x is [ 7, 8, 9 ]
# %hash is (b =>1 )
{
my @nums = delete local @$x[0, 2]
# @nums is (7, 9)
# $x is [ undef, 8 ]
$x[0] = 999; # will be erased when the scope ends
}
# $x is back to [ 7, 8, 9 ]
}
# %hash is back to its original state
T h i s c o n s t r u c t i s s u p p o r t e d s i n c e P e r l v 5 . 1 2 .
# L v a l u e s u b r o u t i n e s
I t i s p o s s i b l e t o r e t u r n a m o d i f i a b l e v a l u e f r o m a s u b r o u t i n e . T o d o t h i s , y o u h a v e t o d e c l a r e t h e s u b r o u t i n e t o r e t u r n a n l v a l u e .
my $val;
sub canmod : lvalue {
$val; # or: return $val;
}
sub nomod {
$val;
}
canmod() = 5; # assigns to $val
nomod() = 5; # ERROR
T h e s c a l a r / l i s t c o n t e x t f o r t h e s u b r o u t i n e a n d f o r t h e r i g h t - h a n d s i d e o f a s s i g n m e n t i s d e t e r m i n e d a s i f t h e s u b r o u t i n e c a l l i s r e p l a c e d b y a s c a l a r . F o r e x a m p l e , c o n s i d e r :
data(2,3) = get_data(3,4);
B o t h s u b r o u t i n e s h e r e a r e c a l l e d i n a s c a l a r c o n t e x t , w h i l e i n :
(data(2,3)) = get_data(3,4);
a n d i n :
(data(2 ),data(3 )) = get_data(3,4);
a l l t h e s u b r o u t i n e s a r e c a l l e d i n a l i s t c o n t e x t .
L v a l u e s u b r o u t i n e s a r e c o n v e n i e n t , b u t y o u h a v e t o k e e p i n m i n d t h a t , w h e n u s e d w i t h o b j e c t s , t h e y m a y v i o l a t e e n c a p s u l a t i o n . A n o r m a l m u t a t o r c a n c h e c k t h e s u p p l i e d a r g u m e n t b e f o r e s e t t i n g t h e a t t r i b u t e i t i s p r o t e c t i n g , a n l v a l u e s u b r o u t i n e c a n n o t . I f y o u r e q u i r e a n y s p e c i a l p r o c e s s i n g w h e n s t o r i n g a n d r e t r i e v i n g t h e v a l u e s , c o n s i d e r u s i n g t h e C P A N m o d u l e S e n t i n e l o r s o m e t h i n g s i m i l a r .
# L e x i c a l S u b r o u t i n e s
B e g i n n i n g w i t h P e r l 5 . 1 8 , y o u c a n d e c l a r e a p r i v a t e s u b r o u t i n e w i t h my
or s t a t e
. A s w i t h s t a t e v a r i a b l e s , t h e s t a t e
k e y w o r d i s o n l y a v a i l a b l e u n d e r u s e f e a t u r e ' s t a
t e '
or u s e v 5 . 1 0
o r h i g h e r .
P r i o r t o P e r l 5 . 2 6 , l e x i c a l s u b r o u t i n e s w e r e d e e m e d e x p e r i m e n t a l a n d w e r e a v a i l a b l e o n l y u n d e r t h e u s e f e a t u r e ' l e x i c a l _ s u b s '
p r a g m a . T h e y a l s o p r o d u c e d a w a r n i n g u n l e s s t h e " e x p e r i m e n t a l : : l e x i c a l _ s u b s " w a r n i n g s c a t e g o r y w a s d i s a b l e d .
T h e s e s u b r o u t i n e s a r e o n l y v i s i b l e w i t h i n t h e b l o c k i n w h i c h t h e y a r e d e c l a r e d , a n d o n l y a f t e r t h a t d e c l a r a t i o n :
# Include these two lines if your code is intended to run under Perl
# versions earlier than 5.26.
no warnings "experimental::lexical_subs";
use feature 'lexical_subs';
foo(); # calls the package/global subroutine
state sub foo {
foo(); # also calls the package subroutine
}
foo(); # calls "state" sub
my $ref = \&foo; # take a reference to "state" sub
my sub bar { ... }
bar(); # calls "my" sub
Y o u c a n ' t ( d i r e c t l y ) w r i t e a r e c u r s i v e l e x i c a l s u b r o u t i n e :
# WRONG
my sub baz {
baz();
}
T h i s e x a m p l e f a i l s b e c a u s e b a z ( )
r e f e r s t o t h e p a c k a g e / g l o b a l s u b r o u t i n e b a z
, n o t t h e l e x i c a l s u b r o u t i n e c u r r e n t l y b e i n g d e f i n e d .
T h e s o l u t i o n i s t o u s e _ _ S U B _ _
:
my sub baz {
__SUB__->(); # calls itself
}
I t i s p o s s i b l e t o p r e d e c l a r e a l e x i c a l s u b r o u t i n e . T h e s u b f o o { .
. . }
s u b r o u t i n e d e f i n i t i o n s y n t a x r e s p e c t s a n y p r e v i o u s m y s u b ;
or s
t a t e s u b ;
d e c l a r a t i o n . U s i n g t h i s t o d e f i n e r e c u r s i v e s u b r o u t i n e s i s a b a d i d e a , h o w e v e r :
my sub baz; # predeclaration
sub baz { # define the "my" sub
baz(); # WRONG: calls itself, but leaks memory
}
J u s t l i k e m y $ f ; $ f = s u b { $ f - >
( ) }
, t h i s e x a m p l e l e a k s m e m o r y . T h e n a m e b a z
i s a r e f e r e n c e t o t h e s u b r o u t i n e , a n d t h e s u b r o u t i n e u s e s t h e n a m e b a z
; t h e y k e e p e a c h o t h e r a l i v e ( s e e " C i r c u l a r R e f e r e n c e s " i n p e r l r e f ) .
# s t a t e s u b
vs m y s u b
W h a t i s t h e d i f f e r e n c e b e t w e e n " s t a t e " s u b s a n d " m y " s u b s ? E a c h t i m e t h a t e x e c u t i o n e n t e r s a b l o c k w h e n " m y " s u b s a r e d e c l a r e d , a n e w c o p y o f e a c h s u b i s c r e a t e d . " S t a t e " s u b r o u t i n e s p e r s i s t f r o m o n e e x e c u t i o n o f t h e c o n t a i n i n g b l o c k t o t h e n e x t .
S o , i n g e n e r a l , " s t a t e " s u b r o u t i n e s a r e f a s t e r . B u t " m y " s u b s a r e n e c e s s a r y i f y o u w a n t t o c r e a t e c l o s u r e s :
sub whatever {
my $x = shift;
my sub inner {
... do something with $x ...
}
inner();
}
I n t h i s e x a m p l e , a n e w $ x
i s c r e a t e d w h e n w h a t e v e r
i s c a l l e d , a n d a l s o a n e w i n n e r
, w h i c h c a n s e e t h e n e w $ x
. A " s t a t e " s u b w i l l o n l y s e e t h e $ x
f r o m t h e f i r s t c a l l t o w h a t e v e r
.
# o u r
s u b r o u t i n e s
L i k e o u r $ v a r i a b l e
, o u r s u b
c r e a t e s a l e x i c a l a l i a s t o t h e p a c k a g e s u b r o u t i n e o f t h e s a m e n a m e .
T h e t w o m a i n u s e s f o r t h i s a r e t o s w i t c h b a c k t o u s i n g t h e p a c k a g e s u b i n s i d e a n i n n e r s c o p e :
sub foo { ... }
sub bar {
my sub foo { ... }
{
# need to use the outer foo here
our sub foo;
foo();
}
}
a n d t o m a k e a s u b r o u t i n e v i s i b l e t o o t h e r p a c k a g e s i n t h e s a m e s c o p e :
package MySneakyModule;
our sub do_something { ... }
sub do_something_with_caller {
package DB;
() = caller 1; # sets @DB::args
do_something(@args); # uses MySneakyModule::do_something
}
# P a s s i n g S y m b o l T a b l e E n t r i e s ( t y p e g l o b s )
W A R N I N G : T h e m e c h a n i s m d e s c r i b e d i n t h i s s e c t i o n w a s o r i g i n a l l y t h e o n l y w a y t o s i m u l a t e p a s s - b y - r e f e r e n c e i n o l d e r v e r s i o n s o f P e r l . W h i l e i t s t i l l w o r k s f i n e i n m o d e r n v e r s i o n s , t h e n e w r e f e r e n c e m e c h a n i s m i s g e n e r a l l y e a s i e r t o w o r k w i t h . S e e b e l o w .
S o m e t i m e s y o u d o n ' t w a n t t o p a s s t h e v a l u e o f a n a r r a y t o a s u b r o u t i n e b u t r a t h e r t h e n a m e o f i t , s o t h a t t h e s u b r o u t i n e c a n m o d i f y t h e g l o b a l c o p y o f i t r a t h e r t h a n w o r k i n g w i t h a l o c a l c o p y . I n P e r l y o u c a n r e f e r t o a l l o b j e c t s o f a p a r t i c u l a r n a m e b y p r e f i x i n g t h e n a m e w i t h a s t a r : * f o
o
. T h i s i s o f t e n k n o w n a s a " t y p e g l o b " , b e c a u s e t h e s t a r o n t h e f r o n t c a n b e t h o u g h t o f a s a w i l d c a r d m a t c h f o r a l l t h e f u n n y p r e f i x c h a r a c t e r s o n v a r i a b l e s a n d s u b r o u t i n e s a n d s u c h .
W h e n e v a l u a t e d , t h e t y p e g l o b p r o d u c e s a s c a l a r v a l u e t h a t r e p r e s e n t s a l l t h e o b j e c t s o f t h a t n a m e , i n c l u d i n g a n y f i l e h a n d l e , f o r m a t , o r s u b r o u t i n e . W h e n a s s i g n e d t o , i t c a u s e s t h e n a m e m e n t i o n e d t o r e f e r t o w h a t e v e r *
v a l u e w a s a s s i g n e d t o i t . E x a m p l e :
sub doubleary {
local(*someary) = @_;
foreach $elem (@someary) {
$elem *= 2;
}
}
doubleary(*foo);
doubleary(*bar);
S c a l a r s a r e a l r e a d y p a s s e d b y r e f e r e n c e , s o y o u c a n m o d i f y s c a l a r a r g u m e n t s w i t h o u t u s i n g t h i s m e c h a n i s m b y r e f e r r i n g e x p l i c i t l y t o $ _ [ 0 ]
e t c . Y o u c a n m o d i f y a l l t h e e l e m e n t s o f a n a r r a y b y p a s s i n g a l l t h e e l e m e n t s a s s c a l a r s , b u t y o u h a v e t o u s e t h e *
m e c h a n i s m ( o r t h e e q u i v a l e n t r e f e r e n c e m e c h a n i s m ) t o p u s h
, p o p
, o r c h a n g e t h e s i z e o f a n a r r a y . I t w i l l c e r t a i n l y b e f a s t e r t o p a s s t h e t y p e g l o b ( o r r e f e r e n c e ) .
E v e n i f y o u d o n ' t w a n t t o m o d i f y a n a r r a y , t h i s m e c h a n i s m i s u s e f u l f o r p a s s i n g m u l t i p l e a r r a y s i n a s i n g l e L I S T , b e c a u s e n o r m a l l y t h e L I S T m e c h a n i s m w i l l m e r g e a l l t h e a r r a y v a l u e s s o t h a t y o u c a n ' t e x t r a c t o u t t h e i n d i v i d u a l a r r a y s . F o r m o r e o n t y p e g l o b s , s e e " T y p e g l o b s a n d F i l e h a n d l e s " i n p e r l d a t a .
# W h e n t o S t i l l U s e l o c a l ( )
D e s p i t e t h e e x i s t e n c e o f my
, t h e r e a r e s t i l l t h r e e p l a c e s w h e r e t h e l o c a l
o p e r a t o r s t i l l s h i n e s . I n f a c t , i n t h e s e t h r e e p l a c e s , y o u m u s t u s e l o c a l
i n s t e a d o f my
.
Y o u n e e d t o g i v e a g l o b a l v a r i a b l e a t e m p o r a r y v a l u e , e s p e c i a l l y $ _ .
T h e g l o b a l v a r i a b l e s , l i k e @ A R G
V
o r t h e p u n c t u a t i o n v a r i a b l e s , m u s t b e l o c a l
i z e d w i t h l o c a l ( )
. T h i s b l o c k r e a d s i n / e t c / m o t d , a n d s p l i t s i t u p i n t o c h u n k s s e p a r a t e d b y l i n e s o f e q u a l s i g n s , w h i c h a r e p l a c e d i n @ F i e l d s
.
{
local @ARGV = ("/etc/motd");
local $/ = undef;
local $_ = <>;
@Fields = split /^\s*=+\s*$/;
}
I t p a r t i c u l a r , i t ' s i m p o r t a n t t o l o c a l
i z e $ _ i n a n y r o u t i n e t h a t a s s i g n s t o i t . L o o k o u t f o r i m p l i c i t a s s i g n m e n t s i n w h i l e
c o n d i t i o n a l s .
Y o u n e e d t o c r e a t e a l o c a l f i l e o r d i r e c t o r y h a n d l e o r a l o c a l f u n c t i o n .
A f u n c t i o n t h a t n e e d s a f i l e h a n d l e o f i t s o w n m u s t u s e l o c a l ( )
o n a c o m p l e t e t y p e g l o b . T h i s c a n b e u s e d t o c r e a t e n e w s y m b o l t a b l e e n t r i e s :
sub ioqueue {
local (*READER, *WRITER); # not my!
pipe (READER, WRITER) or die "pipe: $!";
return (*READER, *WRITER);
}
($head, $tail) = ioqueue();
S e e t h e S y m b o l m o d u l e f o r a w a y t o c r e a t e a n o n y m o u s s y m b o l t a b l e e n t r i e s .
B e c a u s e a s s i g n m e n t o f a r e f e r e n c e t o a t y p e g l o b c r e a t e s a n a l i a s , t h i s c a n b e u s e d t o c r e a t e w h a t i s e f f e c t i v e l y a l o c a l f u n c t i o n , o r a t l e a s t , a l o c a l a l i a s .
{
local *grow = \&shrink; # only until this block exits
grow(); # really calls shrink()
move(); # if move() grow()s, it shrink()s too
}
grow(); # get the real grow() again
S e e " F u n c t i o n T e m p l a t e s " i n p e r l r e f f o r m o r e a b o u t m a n i p u l a t i n g f u n c t i o n s b y n a m e i n t h i s w a y .
Y o u w a n t t o t e m p o r a r i l y c h a n g e j u s t o n e e l e m e n t o f a n a r r a y o r h a s h .
Y o u c a n l o c a l
i z e j u s t o n e e l e m e n t o f a n a g g r e g a t e . U s u a l l y t h i s i s d o n e o n d y n a m i c s :
{
local $SIG{INT} = 'IGNORE';
funct(); # uninterruptible
}
# interruptibility automatically restored here
B u t i t a l s o w o r k s o n l e x i c a l l y d e c l a r e d a g g r e g a t e s .
# P a s s b y R e f e r e n c e
I f y o u w a n t t o p a s s m o r e t h a n o n e a r r a y o r h a s h i n t o a f u n c t i o n - - o r r e t u r n t h e m f r o m i t - - a n d h a v e t h e m m a i n t a i n t h e i r i n t e g r i t y , t h e n y o u ' r e g o i n g t o h a v e t o u s e a n e x p l i c i t p a s s - b y - r e f e r e n c e . B e f o r e y o u d o t h a t , y o u n e e d t o u n d e r s t a n d r e f e r e n c e s a s d e t a i l e d i n p e r l r e f . T h i s s e c t i o n m a y n o t m a k e m u c h s e n s e t o y o u o t h e r w i s e .
H e r e a r e a f e w s i m p l e e x a m p l e s . F i r s t , l e t ' s p a s s i n s e v e r a l a r r a y s t o a f u n c t i o n a n d h a v e i t p o
p
a l l o f t h e n , r e t u r n i n g a n e w l i s t o f a l l t h e i r f o r m e r l a s t e l e m e n t s :
@tailings = popmany ( \@w, \@x, \@y, \@z );
sub popmany {
my $aref;
my @retlist;
foreach $aref ( @_ ) {
push @retlist, pop @$aref;
}
return @retlist;
}
H e r e ' s h o w y o u m i g h t w r i t e a f u n c t i o n t h a t r e t u r n s a l i s t o f k e y s o c c u r r i n g i n a l l t h e h a s h e s p a s s e d t o i t :
@common = inter( \%foo, \%bar, \%joe );
sub inter {
my ($k, $href, %seen); # locals
foreach $href (@_) {
while ( $k = each %$href ) {
$seen{$k}++;
}
}
return grep { $seen{$_} == @_ } keys %seen;
}
S o f a r , w e ' r e u s i n g j u s t t h e n o r m a l l i s t r e t u r n m e c h a n i s m . W h a t h a p p e n s i f y o u w a n t t o p a s s o r r e t u r n a h a s h ? W e l l , i f y o u ' r e u s i n g o n l y o n e o f t h e m , o r y o u d o n ' t m i n d t h e m c o n c a t e n a t i n g , t h e n t h e n o r m a l c a l l i n g c o n v e n t i o n i s o k , a l t h o u g h a l i t t l e e x p e n s i v e .
W h e r e p e o p l e g e t i n t o t r o u b l e i s h e r e :
(@w, @x) = func(@y, @z);
or
(%w, %x) = func(%y, %z);
T h a t s y n t a x s i m p l y w o n ' t w o r k . I t s e t s j u s t @ w
or % w
a n d c l e a r s t h e @ x
or % x
. P l u s t h e f u n c t i o n d i d n ' t g e t p a s s e d i n t o t w o s e p a r a t e a r r a y s o r h a s h e s : i t g o t o n e l o n g l i s t i n @ _
, a s a l w a y s .
I f y o u c a n a r r a n g e f o r e v e r y o n e t o d e a l w i t h t h i s t h r o u g h r e f e r e n c e s , i t ' s c l e a n e r c o d e , a l t h o u g h n o t s o n i c e t o l o o k a t . H e r e ' s a f u n c t i o n t h a t t a k e s t w o a r r a y r e f e r e n c e s a s a r g u m e n t s , r e t u r n i n g t h e t w o a r r a y e l e m e n t s i n o r d e r o f h o w m a n y e l e m e n t s t h e y h a v e i n t h e m :
($wref, $xref) = func(\@y, \@z);
print "@$wref has more than @$xref\n";
sub func {
my ($yref, $zref) = @_;
if (@$yref > @$zref) {
return ($yref, $zref);
} else {
return ($zref, $yref);
}
}
I t t u r n s o u t t h a t y o u c a n a c t u a l l y d o t h i s a l s o :
(*w, *x) = func(\@y, \@z);
print "@w has more than @x\n";
sub func {
local (*y, *z) = @_;
if (@y > @z) {
return (\@y, \@z);
} else {
return (\@z, \@y);
}
}
H e r e w e ' r e u s i n g t h e t y p e g l o b s t o d o s y m b o l t a b l e a l i a s i n g . I t ' s a t a d s u b t l e , t h o u g h , a n d a l s o w o n ' t w o r k i f y o u ' r e u s i n g my
v a r i a b l e s , b e c a u s e o n l y g l o b a l s ( e v e n i n d i s g u i s e a s l o c a l
s ) a r e i n t h e s y m b o l t a b l e .
I f y o u ' r e p a s s i n g a r o u n d f i l e h a n d l e s , y o u c o u l d u s u a l l y j u s t u s e t h e b a r e t y p e g l o b , l i k e * S T D O U T
, b u t t y p e g l o b s r e f e r e n c e s w o r k , t o o . F o r e x a m p l e :
splutter(\*STDOUT);
sub splutter {
my $fh = shift;
print $fh "her um well a hmmm\n";
}
$rec = get_rec(\*STDIN);
sub get_rec {
my $fh = shift;
return scalar <$fh>;
}
I f y o u ' r e p l a n n i n g o n g e n e r a t i n g n e w f i l e h a n d l e s , y o u c o u l d d o t h i s . N o t i c e t o p a s s b a c k j u s t t h e b a r e * F H , n o t i t s r e f e r e n c e .
sub openit {
my $path = shift;
local *FH;
return open (FH, $path) ? *FH : undef;
}
# P r o t o t y p e s
P e r l s u p p o r t s a v e r y l i m i t e d k i n d o f c o m p i l e - t i m e a r g u m e n t c h e c k i n g u s i n g f u n c t i o n p r o t o t y p i n g . T h i s c a n b e d e c l a r e d i n e i t h e r t h e P R O T O s e c t i o n o r w i t h a p r o t o t y p e a t t r i b u t e . I f y o u d e c l a r e e i t h e r o f
sub mypush (\@@)
sub mypush :prototype(\@@)
t h e n m y p u s h ( )
t a k e s a r g u m e n t s e x a c t l y l i k e p u s h ( )
d o e s .
I f s u b r o u t i n e s i g n a t u r e s a r e e n a b l e d ( s e e " S i g n a t u r e s " ) , t h e n t h e s h o r t e r P R O T O s y n t a x i s u n a v a i l a b l e , b e c a u s e i t w o u l d c l a s h w i t h s i g n a t u r e s . I n t h a t c a s e , a p r o t o t y p e c a n o n l y b e d e c l a r e d i n t h e f o r m o f a n a t t r i b u t e .
T h e f u n c t i o n d e c l a r a t i o n m u s t b e v i s i b l e a t c o m p i l e t i m e . T h e p r o t o t y p e a f f e c t s o n l y i n t e r p r e t a t i o n o f r e g u l a r c a l l s t o t h e f u n c t i o n , w h e r e r e g u l a r i s d e f i n e d a s n o t u s i n g t h e &
s i g i l . I n o t h e r w o r d s , i f y o u c a l l i t l i k e a b u i l t - i n f u n c t i o n , t h e n i t b e h a v e s l i k e a b u i l t - i n f u n c t i o n . I f y o u c a l l i t l i k e a n o l d - f a s h i o n e d ( p e r l 4 ) s u b r o u t i n e , t h e n i t b e h a v e s l i k e a n o l d - f a s h i o n e d s u b r o u t i n e . I t n a t u r a l l y f a l l s o u t f r o m t h i s r u l e t h a t p r o t o t y p e s h a v e n o i n f l u e n c e o n s u b r o u t i n e r e f e r e n c e s l i k e \ & f o o
o r o n i n d i r e c t s u b r o u t i n e c a l l s l i k e & { $ s u b r e
f } ( )
or $ s u b r e f - > ( )
.
M e t h o d c a l l s a r e n o t i n f l u e n c e d b y p r o t o t y p e s e i t h e r , b e c a u s e t h e f u n c t i o n t o b e c a l l e d i s i n d e t e r m i n a t e a t c o m p i l e t i m e , s i n c e t h e e x a c t c o d e c a l l e d d e p e n d s o n i n h e r i t a n c e .
B e c a u s e t h e i n t e n t o f t h i s f e a t u r e i s p r i m a r i l y t o l e t y o u d e f i n e s u b r o u t i n e s t h a t w o r k l i k e b u i l t - i n f u n c t i o n s , h e r e a r e p r o t o t y p e s f o r s o m e o t h e r f u n c t i o n s t h a t p a r s e a l m o s t e x a c t l y l i k e t h e c o r r e s p o n d i n g b u i l t - i n .
Declared as Called as
sub mylink ($$) mylink $old, $new
sub myvec ($$$) myvec $var, $offset, 1
sub myindex ($$;$) myindex getstring(), "substr"
sub mysyswrite ($$$;$) mysyswrite $buf, 0, length($buf) - $off, $off
sub myreverse (@) myreverse $x, $y, $z
sub myjoin ($@) myjoin ":", $x, $y, $z
sub mypop (\@) mypop @array
sub mysplice (\@$$@) mysplice @array, 0, 2, @pushme
sub mykeys (\[%@]) mykeys $hashref->%*
sub myopen (*;$) myopen HANDLE, $name
sub mypipe (**) mypipe READHANDLE, WRITEHANDLE
sub mygrep (&@) mygrep { /foo/ } $x, $y, $z
sub myrand (;$) myrand 42
sub mytime () mytime
A n y b a c k s l a s h e d p r o t o t y p e c h a r a c t e r r e p r e s e n t s a n a c t u a l a r g u m e n t t h a t m u s t s t a r t w i t h t h a t c h a r a c t e r ( o p t i o n a l l y p r e c e d e d b y my
, o u r
or l o c a l
) , w i t h t h e e x c e p t i o n o f $
, w h i c h w i l l a c c e p t a n y s c a l a r l v a l u e e x p r e s s i o n , s u c h a s $ f
o o = 7
or m y _ f u n c t i o n ( ) - > [ 0 ]
. T h e v a l u e p a s s e d a s p a r t o f @ _
w i l l b e a r e f e r e n c e t o t h e a c t u a l a r g u m e n t g i v e n i n t h e s u b r o u t i n e c a l l , o b t a i n e d b y a p p l y i n g \
t o t h a t a r g u m e n t .
Y o u c a n u s e t h e \ [ ]
b a c k s l a s h g r o u p n o t a t i o n t o s p e c i f y m o r e t h a n o n e a l l o w e d a r g u m e n t t y p e . F o r e x a m p l e :
sub myref (\[$@%&*])
w i l l a l l o w c a l l i n g m y r e f ( ) a s
myref $var
myref @array
myref %hash
myref &sub
myref *glob
a n d t h e f i r s t a r g u m e n t o f m y r e f ( ) w i l l b e a r e f e r e n c e t o a s c a l a r , a n a r r a y , a h a s h , a s u b r o u t i n e , o r a g l o b .
U n b a c k s l a s h e d p r o t o t y p e c h a r a c t e r s h a v e s p e c i a l m e a n i n g s . A n y u n b a c k s l a s h e d @
or %
e a t s a l l r e m a i n i n g a r g u m e n t s , a n d f o r c e s l i s t c o n t e x t . A n a r g u m e n t r e p r e s e n t e d b y $
f o r c e s s c a l a r c o n t e x t . A n &
r e q u i r e s a n a n o n y m o u s s u b r o u t i n e , w h i c h , i f p a s s e d a s t h e f i r s t a r g u m e n t , m a y l o o k l i k e a b a r e b l o c k : I t d o e s n o t r e q u i r e t h e s u b
k e y w o r d o r a s u b s e q u e n t c o m m a .
A *
a l l o w s t h e s u b r o u t i n e t o a c c e p t a b a r e w o r d , c o n s t a n t , s c a l a r e x p r e s s i o n , t y p e g l o b , o r a r e f e r e n c e t o a t y p e g l o b i n t h a t s l o t . T h e v a l u e w i l l b e a v a i l a b l e t o t h e s u b r o u t i n e e i t h e r a s a s i m p l e s c a l a r , o r ( i n t h e l a t t e r t w o c a s e s ) a s a r e f e r e n c e t o t h e t y p e g l o b . I f y o u w i s h t o a l w a y s c o n v e r t s u c h a r g u m e n t s t o a t y p e g l o b r e f e r e n c e , u s e S y m b o l : : q u a l i f y _ t o _ r e f ( ) a s f o l l o w s :
use Symbol 'qualify_to_ref';
sub foo (*) {
my $fh = qualify_to_ref(shift, caller);
...
}
T h e +
p r o t o t y p e i s a s p e c i a l a l t e r n a t i v e t o $
t h a t w i l l a c t l i k e \ [ @ % ]
w h e n g i v e n a l i t e r a l a r r a y o r h a s h v a r i a b l e , b u t w i l l o t h e r w i s e f o r c e s c a l a r c o n t e x t o n t h e a r g u m e n t . T h i s i s u s e f u l f o r f u n c t i o n s w h i c h s h o u l d a c c e p t e i t h e r a l i t e r a l a r r a y o r a n a r r a y r e f e r e n c e a s t h e a r g u m e n t :
sub mypush (+@) {
my $aref = shift;
die "Not an array or arrayref" unless ref $aref eq 'ARRAY';
push @$aref, @_;
}
W h e n u s i n g t h e +
p r o t o t y p e , y o u r f u n c t i o n m u s t c h e c k t h a t t h e a r g u m e n t i s o f a n a c c e p t a b l e t y p e .
A s e m i c o l o n ( ;
) s e p a r a t e s m a n d a t o r y a r g u m e n t s f r o m o p t i o n a l a r g u m e n t s . I t i s r e d u n d a n t b e f o r e @
or %
, w h i c h g o b b l e u p e v e r y t h i n g e l s e .
A s t h e l a s t c h a r a c t e r o f a p r o t o t y p e , o r j u s t b e f o r e a s e m i c o l o n , a @
o r a %
, y o u c a n u s e _
i n p l a c e o f $
: i f t h i s a r g u m e n t i s n o t p r o v i d e d , $ _
w i l l b e u s e d i n s t e a d .
N o t e h o w t h e l a s t t h r e e e x a m p l e s i n t h e t a b l e a b o v e a r e t r e a t e d s p e c i a l l y b y t h e p a r s e r . m y g r e p ( )
i s p a r s e d a s a t r u e l i s t o p e r a t o r , m y r a n d ( )
i s p a r s e d a s a t r u e u n a r y o p e r a t o r w i t h u n a r y p r e c e d e n c e t h e s a m e a s r a n d ( )
, a n d m y
t i m e ( )
i s t r u l y w i t h o u t a r g u m e n t s , j u s t l i k e t i m e ( )
. T h a t i s , i f y o u s a y
mytime +2;
y o u ' l l g e t m y t i m e ( ) + 2
, n o t m y t
i m e ( 2 )
, w h i c h i s h o w i t w o u l d b e p a r s e d w i t h o u t a p r o t o t y p e . I f y o u w a n t t o f o r c e a u n a r y f u n c t i o n t o h a v e t h e s a m e p r e c e d e n c e a s a l i s t o p e r a t o r , a d d ;
t o t h e e n d o f t h e p r o t o t y p e :
sub mygetprotobynumber($;);
mygetprotobynumber $x > $y; # parsed as mygetprotobynumber($x > $y)
T h e i n t e r e s t i n g t h i n g a b o u t &
i s t h a t y o u c a n g e n e r a t e n e w s y n t a x w i t h i t , p r o v i d e d i t ' s i n t h e i n i t i a l p o s i t i o n :
sub try (&@) {
my($try,$catch) = @_;
eval { &$try };
if ($@) {
local $_ = $@;
&$catch;
}
}
sub catch (&) { $_[0] }
try {
die "phooey";
} catch {
/phooey/ and print "unphooey\n";
};
T h a t p r i n t s " u n p h o o e y "
. ( Y e s , t h e r e a r e s t i l l u n r e s o l v e d i s s u e s h a v i n g t o d o w i t h v i s i b i l i t y o f @ _
. I ' m i g n o r i n g t h a t q u e s t i o n f o r t h e m o m e n t . ( B u t n o t e t h a t i f w e m a k e @ _
l e x i c a l l y s c o p e d , t h o s e a n o n y m o u s s u b r o u t i n e s c a n a c t l i k e c l o s u r e s . . . ( G e e , i s t h i s s o u n d i n g a l i t t l e L i s p i s h ? ( N e v e r m i n d . ) ) ) )
A n d h e r e ' s a r e i m p l e m e n t a t i o n o f t h e P e r l g r e p
o p e r a t o r :
sub mygrep (&@) {
my $code = shift;
my @result;
foreach $_ (@_) {
push(@result, $_) if &$code;
}
@result;
}
S o m e f o l k s w o u l d p r e f e r f u l l a l p h a n u m e r i c p r o t o t y p e s . A l p h a n u m e r i c s h a v e b e e n i n t e n t i o n a l l y l e f t o u t o f p r o t o t y p e s f o r t h e e x p r e s s p u r p o s e o f s o m e d a y i n t h e f u t u r e a d d i n g n a m e d , f o r m a l p a r a m e t e r s . T h e c u r r e n t m e c h a n i s m ' s m a i n g o a l i s t o l e t m o d u l e w r i t e r s p r o v i d e b e t t e r d i a g n o s t i c s f o r m o d u l e u s e r s . L a r r y f e e l s t h e n o t a t i o n q u i t e u n d e r s t a n d a b l e t o P e r l p r o g r a m m e r s , a n d t h a t i t w i l l n o t i n t r u d e g r e a t l y u p o n t h e m e a t o f t h e m o d u l e , n o r m a k e i t h a r d e r t o r e a d . T h e l i n e n o i s e i s v i s u a l l y e n c a p s u l a t e d i n t o a s m a l l p i l l t h a t ' s e a s y t o s w a l l o w .
I f y o u t r y t o u s e a n a l p h a n u m e r i c s e q u e n c e i n a p r o t o t y p e y o u w i l l g e n e r a t e a n o p t i o n a l w a r n i n g - " I l l e g a l c h a r a c t e r i n p r o t o t y p e . . . " . U n f o r t u n a t e l y e a r l i e r v e r s i o n s o f P e r l a l l o w e d t h e p r o t o t y p e t o b e u s e d a s l o n g a s i t s p r e f i x w a s a v a l i d p r o t o t y p e . T h e w a r n i n g m a y b e u p g r a d e d t o a f a t a l e r r o r i n a f u t u r e v e r s i o n o f P e r l o n c e t h e m a j o r i t y o f o f f e n d i n g c o d e i s f i x e d .
I t ' s p r o b a b l y b e s t t o p r o t o t y p e n e w f u n c t i o n s , n o t r e t r o f i t p r o t o t y p i n g i n t o o l d e r o n e s . T h a t ' s b e c a u s e y o u m u s t b e e s p e c i a l l y c a r e f u l a b o u t s i l e n t i m p o s i t i o n s o f d i f f e r i n g l i s t v e r s u s s c a l a r c o n t e x t s . F o r e x a m p l e , i f y o u d e c i d e t h a t a f u n c t i o n s h o u l d t a k e j u s t o n e p a r a m e t e r , l i k e t h i s :
sub func ($) {
my $n = shift;
print "you gave me $n\n";
}
a n d s o m e o n e h a s b e e n c a l l i n g i t w i t h a n a r r a y o r e x p r e s s i o n r e t u r n i n g a l i s t :
func(@foo);
func( $text =~ /\w+/g );
T h e n y o u ' v e j u s t s u p p l i e d a n a u t o m a t i c s c a l a r
i n f r o n t o f t h e i r a r g u m e n t , w h i c h c a n b e m o r e t h a n a b i t s u r p r i s i n g . T h e o l d @ f o o
w h i c h u s e d t o h o l d o n e t h i n g d o e s n ' t g e t p a s s e d i n . I n s t e a d , f u n
c ( )
n o w g e t s p a s s e d i n a 1
; t h a t i s , t h e n u m b e r o f e l e m e n t s i n @
f o o
. A n d t h e m / / g
g e t s c a l l e d i n s c a l a r c o n t e x t s o i n s t e a d o f a l i s t o f w o r d s i t r e t u r n s a b o o l e a n r e s u l t a n d a d v a n c e s p o s ( $ t e x t )
. O u c h !
I f a s u b h a s b o t h a P R O T O a n d a B L O C K , t h e p r o t o t y p e i s n o t a p p l i e d u n t i l a f t e r t h e B L O C K i s c o m p l e t e l y d e f i n e d . T h i s m e a n s t h a t a r e c u r s i v e f u n c t i o n w i t h a p r o t o t y p e h a s t o b e p r e d e c l a r e d f o r t h e p r o t o t y p e t o t a k e e f f e c t , l i k e s o :
sub foo($$);
sub foo($$) {
foo 1, 2;
}
T h i s i s a l l v e r y p o w e r f u l , o f c o u r s e , a n d s h o u l d b e u s e d o n l y i n m o d e r a t i o n t o m a k e t h e w o r l d a b e t t e r p l a c e .
# C o n s t a n t F u n c t i o n s
F u n c t i o n s w i t h a p r o t o t y p e o f ( )
a r e p o t e n t i a l c a n d i d a t e s f o r i n l i n i n g . I f t h e r e s u l t a f t e r o p t i m i z a t i o n a n d c o n s t a n t f o l d i n g i s e i t h e r a c o n s t a n t o r a l e x i c a l l y - s c o p e d s c a l a r w h i c h h a s n o o t h e r r e f e r e n c e s , t h e n i t w i l l b e u s e d i n p l a c e o f f u n c t i o n c a l l s m a d e w i t h o u t &
. C a l l s m a d e u s i n g &
a r e n e v e r i n l i n e d . ( S e e c o n s t a n t f o r a n e a s y w a y t o d e c l a r e m o s t c o n s t a n t s . )
T h e f o l l o w i n g f u n c t i o n s w o u l d a l l b e i n l i n e d :
sub pi () { 3.14159 } # Not exact, but close.
sub PI () { 4 * atan2 1, 1 } # As good as it gets,
# and it's inlined, too!
sub ST_DEV () { 0 }
sub ST_INO () { 1 }
sub FLAG_FOO () { 1 << 8 }
sub FLAG_BAR () { 1 << 9 }
sub FLAG_MASK () { FLAG_FOO | FLAG_BAR }
sub OPT_BAZ () { not (0x1B58 & FLAG_MASK) }
sub N () { int(OPT_BAZ) / 3 }
sub FOO_SET () { 1 if FLAG_MASK & FLAG_FOO }
sub FOO_SET2 () { if (FLAG_MASK & FLAG_FOO) { 1 } }
( B e a w a r e t h a t t h e l a s t e x a m p l e w a s n o t a l w a y s i n l i n e d i n P e r l 5 . 2 0 a n d e a r l i e r , w h i c h d i d n o t b e h a v e c o n s i s t e n t l y w i t h s u b r o u t i n e s c o n t a i n i n g i n n e r s c o p e s . ) Y o u c a n c o u n t e r m a n d i n l i n i n g b y u s i n g a n e x p l i c i t r e t u r n
:
sub baz_val () {
if (OPT_BAZ) {
return 23;
}
else {
return 42;
}
}
sub bonk_val () { return 12345 }
A s a l l u d e d t o e a r l i e r y o u c a n a l s o d e c l a r e i n l i n e d s u b s d y n a m i c a l l y a t B E G I N t i m e i f t h e i r b o d y c o n s i s t s o f a l e x i c a l l y - s c o p e d s c a l a r w h i c h h a s n o o t h e r r e f e r e n c e s . O n l y t h e f i r s t e x a m p l e h e r e w i l l b e i n l i n e d :
BEGIN {
my $var = 1;
no strict 'refs';
*INLINED = sub () { $var };
}
BEGIN {
my $var = 1;
my $ref = \$var;
no strict 'refs';
*NOT_INLINED = sub () { $var };
}
A n o t s o o b v i o u s c a v e a t w i t h t h i s ( s e e [ R T # 7 9 9 0 8 ] ) i s w h a t h a p p e n s i f t h e v a r i a b l e i s p o t e n t i a l l y m o d i f i a b l e . F o r e x a m p l e :
BEGIN {
my $x = 10;
*FOO = sub () { $x };
$x++;
}
print FOO(); # printed 10 prior to 5.32.0
F r o m P e r l 5 . 2 2 o n w a r d s t h i s g a v e a d e p r e c a t i o n w a r n i n g , a n d f r o m P e r l 5 . 3 2 o n w a r d s i t b e c a m e a r u n - t i m e e r r o r . P r e v i o u s l y t h e v a r i a b l e w a s i m m e d i a t e l y i n l i n e d , a n d s t o p p e d b e h a v i n g l i k e a n o r m a l l e x i c a l v a r i a b l e ; s o i t p r i n t e d 10
, n o t 11
.
I f y o u s t i l l w a n t s u c h a s u b r o u t i n e t o b e i n l i n e d ( w i t h n o w a r n i n g ) , m a k e s u r e t h e v a r i a b l e i s n o t u s e d i n a c o n t e x t w h e r e i t c o u l d b e m o d i f i e d a s i d e f r o m w h e r e i t i s d e c l a r e d .
# Fine, no warning
BEGIN {
my $x = 54321;
*INLINED = sub () { $x };
}
# Error
BEGIN {
my $x;
$x = 54321;
*ALSO_INLINED = sub () { $x };
}
P e r l 5 . 2 2 a l s o i n t r o d u c e d t h e " c o n s t " a t t r i b u t e a s a n a l t e r n a t i v e . I t w a s i n i t i a l l y e x p e r i m e n t a l , b u t m a d e s t a b l e i n P e r l 5 . 4 0 . W h e n a p p l i e d t o a n a n o n y m o u s s u b r o u t i n e , i t f o r c e s t h e s u b t o b e c a l l e d w h e n t h e s u b
e x p r e s s i o n i s e v a l u a t e d . T h e r e t u r n v a l u e i s c a p t u r e d a n d t u r n e d i n t o a c o n s t a n t s u b r o u t i n e :
my $x = 54321;
*INLINED = sub : const { $x };
$x++;
T h e r e t u r n v a l u e o f I N L I N E D
i n t h i s e x a m p l e w i l l a l w a y s b e 5 4 3 2 1 , r e g a r d l e s s o f l a t e r m o d i f i c a t i o n s t o $ x . Y o u c a n a l s o p u t a n y a r b i t r a r y c o d e i n s i d e t h e s u b , a t i t w i l l b e e x e c u t e d i m m e d i a t e l y a n d i t s r e t u r n v a l u e c a p t u r e d t h e s a m e w a y .
I f y o u r e a l l y w a n t a s u b r o u t i n e w i t h a ( )
p r o t o t y p e t h a t r e t u r n s a l e x i c a l v a r i a b l e y o u c a n e a s i l y f o r c e i t t o n o t b e i n l i n e d b y a d d i n g a n e x p l i c i t r e t u r n
:
BEGIN {
my $x = 10;
*FOO = sub () { return $x };
$x++;
}
print FOO(); # prints 11
T h e e a s i e s t w a y t o t e l l i f a s u b r o u t i n e w a s i n l i n e d i s b y u s i n g B : : D e p a r s e . C o n s i d e r t h i s e x a m p l e o f t w o s u b r o u t i n e s r e t u r n i n g 1
, o n e w i t h a ( )
p r o t o t y p e c a u s i n g i t t o b e i n l i n e d , a n d o n e w i t h o u t ( w i t h d e p a r s e o u t p u t t r u n c a t e d f o r c l a r i t y ) :
$ perl -MO=Deparse -e 'sub ONE { 1 } if (ONE) { print ONE if ONE }'
sub ONE {
1;
}
if (ONE ) {
print ONE() if ONE ;
}
$ perl -MO=Deparse -e 'sub ONE () { 1 } if (ONE) { print ONE if ONE }'
sub ONE () { 1 }
do {
print 1
};
I f y o u r e d e f i n e a s u b r o u t i n e t h a t w a s e l i g i b l e f o r i n l i n i n g , y o u ' l l g e t a w a r n i n g b y d e f a u l t . Y o u c a n u s e t h i s w a r n i n g t o t e l l w h e t h e r o r n o t a p a r t i c u l a r s u b r o u t i n e i s c o n s i d e r e d i n l i n a b l e , s i n c e i t ' s d i f f e r e n t t h a n t h e w a r n i n g f o r o v e r r i d i n g n o n - i n l i n e d s u b r o u t i n e s :
$ perl -e 'sub one () {1} sub one () {2}'
Constant subroutine one redefined at -e line 1.
$ perl -we 'sub one {1} sub one {2}'
Subroutine one redefined at -e line 1.
T h e w a r n i n g i s c o n s i d e r e d s e v e r e e n o u g h n o t t o b e a f f e c t e d b y t h e - w s w i t c h ( o r i t s a b s e n c e ) b e c a u s e p r e v i o u s l y c o m p i l e d i n v o c a t i o n s o f t h e f u n c t i o n w i l l s t i l l b e u s i n g t h e o l d v a l u e o f t h e f u n c t i o n . I f y o u n e e d t o b e a b l e t o r e d e f i n e t h e s u b r o u t i n e , y o u n e e d t o e n s u r e t h a t i t i s n ' t i n l i n e d , e i t h e r b y d r o p p i n g t h e ( )
p r o t o t y p e ( w h i c h c h a n g e s c a l l i n g s e m a n t i c s , s o b e w a r e ) o r b y t h w a r t i n g t h e i n l i n i n g m e c h a n i s m i n s o m e o t h e r w a y , e . g . b y a d d i n g a n e x p l i c i t r e t u r n
, a s m e n t i o n e d a b o v e :
sub not_inlined () { return 23 }
# O v e r r i d i n g B u i l t - i n F u n c t i o n s
M a n y b u i l t - i n f u n c t i o n s m a y b e o v e r r i d d e n , t h o u g h t h i s s h o u l d b e t r i e d o n l y o c c a s i o n a l l y a n d f o r g o o d r e a s o n . T y p i c a l l y t h i s m i g h t b e d o n e b y a p a c k a g e a t t e m p t i n g t o e m u l a t e m i s s i n g b u i l t - i n f u n c t i o n a l i t y o n a n o n - U n i x s y s t e m .
O v e r r i d i n g m a y b e d o n e o n l y b y i m p o r t i n g t h e n a m e f r o m a m o d u l e a t c o m p i l e t i m e - - o r d i n a r y p r e d e c l a r a t i o n i s n ' t g o o d e n o u g h . H o w e v e r , t h e u s e s u b s
p r a g m a l e t s y o u , i n e f f e c t , p r e d e c l a r e s u b s v i a t h e i m p o r t s y n t a x , a n d t h e s e n a m e s m a y t h e n o v e r r i d e b u i l t - i n o n e s :
use subs 'chdir', 'chroot', 'chmod', 'chown';
chdir $somewhere;
sub chdir { ... }
T o u n a m b i g u o u s l y r e f e r t o t h e b u i l t - i n f o r m , p r e c e d e t h e b u i l t - i n n a m e w i t h t h e s p e c i a l p a c k a g e q u a l i f i e r C O R E : :
. F o r e x a m p l e , s a y i n g C O R E : : o p e n ( )
a l w a y s r e f e r s t o t h e b u i l t - i n o p e n ( )
, e v e n i f t h e c u r r e n t p a c k a g e h a s i m p o r t e d s o m e o t h e r s u b r o u t i n e c a l l e d &
o p e n ( )
f r o m e l s e w h e r e . E v e n t h o u g h i t l o o k s l i k e a r e g u l a r f u n c t i o n c a l l , i t i s n ' t : t h e C O R E : :
p r e f i x i n t h a t c a s e i s p a r t o f P e r l ' s s y n t a x , a n d w o r k s f o r a n y k e y w o r d , r e g a r d l e s s o f w h a t i s i n t h e C O R E
p a c k a g e . T a k i n g a r e f e r e n c e t o i t , t h a t i s , \ & C O R E : : o p
e n
, o n l y w o r k s f o r s o m e k e y w o r d s . S e e C O R E .
L i b r a r y m o d u l e s s h o u l d n o t i n g e n e r a l e x p o r t b u i l t - i n n a m e s l i k e o p e n
or c h d i r
a s p a r t o f t h e i r d e f a u l t @ E X P O R T
l i s t , b e c a u s e t h e s e m a y s n e a k i n t o s o m e o n e e l s e ' s n a m e s p a c e a n d c h a n g e t h e s e m a n t i c s u n e x p e c t e d l y . I n s t e a d , i f t h e m o d u l e a d d s t h a t n a m e t o @ E X P O R T
_ O K
, t h e n i t ' s p o s s i b l e f o r a u s e r t o i m p o r t t h e n a m e e x p l i c i t l y , b u t n o t i m p l i c i t l y . T h a t i s , t h e y c o u l d s a y
use Module 'open';
a n d i t w o u l d i m p o r t t h e o p e n
o v e r r i d e . B u t i f t h e y s a i d
use Module;
t h e y w o u l d g e t t h e d e f a u l t i m p o r t s w i t h o u t o v e r r i d e s .
T h e f o r e g o i n g m e c h a n i s m f o r o v e r r i d i n g b u i l t - i n i s r e s t r i c t e d , q u i t e d e l i b e r a t e l y , t o t h e p a c k a g e t h a t r e q u e s t s t h e i m p o r t . T h e r e i s a s e c o n d m e t h o d t h a t i s s o m e t i m e s a p p l i c a b l e w h e n y o u w i s h t o o v e r r i d e a b u i l t - i n e v e r y w h e r e , w i t h o u t r e g a r d t o n a m e s p a c e b o u n d a r i e s . T h i s i s a c h i e v e d b y i m p o r t i n g a s u b i n t o t h e s p e c i a l n a m e s p a c e C O R E : : G L O B A L : :
. H e r e i s a n e x a m p l e t h a t q u i t e b r a z e n l y r e p l a c e s t h e g l o b
o p e r a t o r w i t h s o m e t h i n g t h a t u n d e r s t a n d s r e g u l a r e x p r e s s i o n s .
package REGlob;
require Exporter;
@ISA = 'Exporter';
@EXPORT_OK = 'glob';
sub import {
my $pkg = shift;
return unless @_;
my $sym = shift;
my $where = ($sym =~ s/^GLOBAL_// ? 'CORE::GLOBAL' : caller(0));
$pkg->export($where, $sym, @_);
}
sub glob {
my $pat = shift;
my @got;
if (opendir my $d, '.') {
@got = grep /$pat/, readdir $d;
closedir $d;
}
return @got;
}
1;
A n d h e r e ' s h o w i t c o u l d b e ( ab ) u s e d :
#use REGlob 'GLOBAL_glob'; # override glob() in ALL namespaces
package Foo;
use REGlob 'glob'; # override glob() in Foo:: only
print for <^[a-z_]+\.pm\$>; # show all pragmatic modules
T h e i n i t i a l c o m m e n t s h o w s a c o n t r i v e d , e v e n d a n g e r o u s e x a m p l e . B y o v e r r i d i n g g l o b
g l o b a l l y , y o u w o u l d b e f o r c i n g t h e n e w ( a n d s u b v e r s i v e ) b e h a v i o r f o r t h e g l o b
o p e r a t o r f o r e v e r y n a m e s p a c e , w i t h o u t t h e c o m p l e t e c o g n i z a n c e o r c o o p e r a t i o n o f t h e m o d u l e s t h a t o w n t h o s e n a m e s p a c e s . N a t u r a l l y , t h i s s h o u l d b e d o n e w i t h e x t r e m e c a u t i o n - - i f i t m u s t b e d o n e a t a l l .
T h e R E G l o b
e x a m p l e a b o v e d o e s n o t i m p l e m e n t a l l t h e s u p p o r t n e e d e d t o c l e a n l y o v e r r i d e P e r l ' s g l o
b
o p e r a t o r . T h e b u i l t - i n g l o b
h a s d i f f e r e n t b e h a v i o r s d e p e n d i n g o n w h e t h e r i t a p p e a r s i n a s c a l a r o r l i s t c o n t e x t , b u t o u r R E G l o
b
d o e s n ' t . I n d e e d , m a n y P e r l b u i l t - i n s h a v e s u c h c o n t e x t s e n s i t i v e b e h a v i o r s , a n d t h e s e m u s t b e a d e q u a t e l y s u p p o r t e d b y a p r o p e r l y w r i t t e n o v e r r i d e . F o r a f u l l y f u n c t i o n a l e x a m p l e o f o v e r r i d i n g g l o b
, s t u d y t h e i m p l e m e n t a t i o n o f F i l e : : D o s G l o b
i n t h e s t a n d a r d l i b r a r y .
W h e n y o u o v e r r i d e a b u i l t - i n , y o u r r e p l a c e m e n t s h o u l d b e c o n s i s t e n t ( i f p o s s i b l e ) w i t h t h e b u i l t - i n n a t i v e s y n t a x . Y o u c a n a c h i e v e t h i s b y u s i n g a s u i t a b l e p r o t o t y p e . T o g e t t h e p r o t o t y p e o f a n o v e r r i d a b l e b u i l t - i n , u s e t h e p r o t o t y p e
f u n c t i o n w i t h a n a r g u m e n t o f " C O R E : : b u i l t i n _ n a m e "
( s e e " p r o t o t y p e " i n p e r l f u n c ) .
N o t e h o w e v e r t h a t s o m e b u i l t - i n s c a n ' t h a v e t h e i r s y n t a x e x p r e s s e d b y a p r o t o t y p e ( s u c h a s s y s t e
m
or c h o m p
) . I f y o u o v e r r i d e t h e m y o u w o n ' t b e a b l e t o f u l l y m i m i c t h e i r o r i g i n a l s y n t a x .
T h e b u i l t - i n s do
, r e q u i r e
a n d g l o
b
c a n a l s o b e o v e r r i d d e n , b u t d u e t o s p e c i a l m a g i c , t h e i r o r i g i n a l s y n t a x i s p r e s e r v e d , a n d y o u d o n ' t h a v e t o d e f i n e a p r o t o t y p e f o r t h e i r r e p l a c e m e n t s . ( Y o u c a n ' t o v e r r i d e t h e d o B L O C K
s y n t a x , t h o u g h ) .
r e q u i r e
h a s s p e c i a l a d d i t i o n a l d a r k m a g i c : i f y o u i n v o k e y o u r r e
q u i r e
r e p l a c e m e n t a s r e q u i r e F o o
: : B a r
, i t w i l l a c t u a l l y r e c e i v e t h e a r g u m e n t " F o o / B a r . p m "
i n @ _ . S e e " r e q u i r e " i n p e r l f u n c .
A n d , a s y o u ' l l h a v e n o t i c e d f r o m t h e p r e v i o u s e x a m p l e , i f y o u o v e r r i d e g l o b
, t h e < * >
g l o b o p e r a t o r i s o v e r r i d d e n a s w e l l .
I n a s i m i l a r f a s h i o n , o v e r r i d i n g t h e r e a d l i n e
f u n c t i o n a l s o o v e r r i d e s t h e e q u i v a l e n t I / O o p e r a t o r < F I L E H A N D L E >
. A l s o , o v e r r i d i n g r e a d p i p e
a l s o o v e r r i d e s t h e o p e r a t o r s ` `
a n d q x / /
.
F i n a l l y , s o m e b u i l t - i n s ( e . g . e x
i s t s
or g r e p
) c a n ' t b e o v e r r i d d e n .
# A u t o l o a d i n g
I f y o u c a l l a s u b r o u t i n e t h a t i s u n d e f i n e d , y o u w o u l d o r d i n a r i l y g e t a n i m m e d i a t e , f a t a l e r r o r c o m p l a i n i n g t h a t t h e s u b r o u t i n e d o e s n ' t e x i s t . ( L i k e w i s e f o r s u b r o u t i n e s b e i n g u s e d a s m e t h o d s , w h e n t h e m e t h o d d o e s n ' t e x i s t i n a n y b a s e c l a s s o f t h e c l a s s ' s p a c k a g e . ) H o w e v e r , i f a n A U T O L O A D
s u b r o u t i n e i s d e f i n e d i n t h e p a c k a g e o r p a c k a g e s u s e d t o l o c a t e t h e o r i g i n a l s u b r o u t i n e , t h e n t h a t A U T O L O A D
s u b r o u t i n e i s c a l l e d w i t h t h e a r g u m e n t s t h a t w o u l d h a v e b e e n p a s s e d t o t h e o r i g i n a l s u b r o u t i n e . T h e f u l l y q u a l i f i e d n a m e o f t h e o r i g i n a l s u b r o u t i n e m a g i c a l l y a p p e a r s i n t h e g l o b a l $ A U T O L O A D v a r i a b l e o f t h e s a m e p a c k a g e a s t h e A U T O L O A D
r o u t i n e . T h e n a m e i s n o t p a s s e d a s a n o r d i n a r y a r g u m e n t b e c a u s e , e r , w e l l , j u s t b e c a u s e , t h a t ' s w h y . ( A s a n e x c e p t i o n , a m e t h o d c a l l t o a n o n e x i s t e n t i m p o r t
or u n i m p o r t
m e t h o d i s j u s t s k i p p e d i n s t e a d . A l s o , i f t h e A U T O L O A D s u b r o u t i n e i s a n X S U B , t h e r e a r e o t h e r w a y s t o r e t r i e v e t h e s u b r o u t i n e n a m e . S e e " A u t o l o a d i n g w i t h X S U B s " i n p e r l g u t s f o r d e t a i l s . )
M a n y A U T O L O A D
r o u t i n e s l o a d i n a d e f i n i t i o n f o r t h e r e q u e s t e d s u b r o u t i n e u s i n g e v a l ( ) , t h e n e x e c u t e t h a t s u b r o u t i n e u s i n g a s p e c i a l f o r m o f g o t o ( ) t h a t e r a s e s t h e s t a c k f r a m e o f t h e A U T O L O A D
r o u t i n e w i t h o u t a t r a c e . ( S e e t h e s o u r c e t o t h e s t a n d a r d m o d u l e d o c u m e n t e d i n A u t o L o a d e r , f o r e x a m p l e . ) B u t a n A U T O L O A D
r o u t i n e c a n a l s o j u s t e m u l a t e t h e r o u t i n e a n d n e v e r d e f i n e i t . F o r e x a m p l e , l e t ' s p r e t e n d t h a t a f u n c t i o n t h a t w a s n ' t d e f i n e d s h o u l d j u s t i n v o k e s y s t e m
w i t h t h o s e a r g u m e n t s . A l l y o u ' d d o i s :
sub AUTOLOAD {
our $AUTOLOAD; # keep 'use strict' happy
my $program = $AUTOLOAD;
$program =~ s/.*:://;
system($program, @_);
}
date();
who();
ls('-l');
I n f a c t , i f y o u p r e d e c l a r e f u n c t i o n s y o u w a n t t o c a l l t h a t w a y , y o u d o n ' t e v e n n e e d p a r e n t h e s e s :
use subs qw(date who ls);
date;
who;
ls '-l';
A m o r e c o m p l e t e e x a m p l e o f t h i s i s t h e S h e l l m o d u l e o n C P A N , w h i c h c a n t r e a t u n d e f i n e d s u b r o u t i n e c a l l s a s c a l l s t o e x t e r n a l p r o g r a m s .
M e c h a n i s m s a r e a v a i l a b l e t o h e l p m o d u l e s w r i t e r s s p l i t t h e i r m o d u l e s i n t o a u t o l o a d a b l e f i l e s . S e e t h e s t a n d a r d A u t o L o a d e r m o d u l e d e s c r i b e d i n A u t o L o a d e r a n d i n A u t o S p l i t , t h e s t a n d a r d S e l f L o a d e r m o d u l e s i n S e l f L o a d e r , a n d t h e d o c u m e n t o n a d d i n g C f u n c t i o n s t o P e r l c o d e i n p e r l x s .
# S u b r o u t i n e A t t r i b u t e s
A s u b r o u t i n e d e c l a r a t i o n o r d e f i n i t i o n m a y h a v e a l i s t o f a t t r i b u t e s a s s o c i a t e d w i t h i t . I f s u c h a n a t t r i b u t e l i s t i s p r e s e n t , i t i s b r o k e n u p a t s p a c e o r c o l o n b o u n d a r i e s a n d t r e a t e d a s t h o u g h a u s e a t t r i b u t e s
h a d b e e n s e e n . S e e a t t r i b u t e s f o r d e t a i l s a b o u t w h a t a t t r i b u t e s a r e c u r r e n t l y s u p p o r t e d . U n l i k e t h e l i m i t a t i o n w i t h t h e o b s o l e s c e n t u s e a t t r s
, t h e s u b : A T T R L I S T
s y n t a x w o r k s t o a s s o c i a t e t h e a t t r i b u t e s w i t h a p r e - d e c l a r a t i o n , a n d n o t j u s t w i t h a s u b r o u t i n e d e f i n i t i o n .
T h e a t t r i b u t e s m u s t b e v a l i d a s s i m p l e i d e n t i f i e r n a m e s ( w i t h o u t a n y p u n c t u a t i o n o t h e r t h a n t h e ' _ ' c h a r a c t e r ) . T h e y m a y h a v e a p a r a m e t e r l i s t a p p e n d e d , w h i c h i s o n l y c h e c k e d f o r w h e t h e r i t s p a r e n t h e s e s ( ' ( ' , ' ) ' ) n e s t p r o p e r l y .
E x a m p l e s o f v a l i d s y n t a x ( e v e n t h o u g h t h e a t t r i b u t e s a r e u n k n o w n ) :
sub fnord (&\%) : switch(10,foo(7,3)) : expensive;
sub plugh () : Ugly('\(") :Bad;
sub xyzzy : _5x5 { ... }
E x a m p l e s o f i n v a l i d s y n t a x :
sub fnord : switch(10,foo(); # ()-string not balanced
sub snoid : Ugly('('); # ()-string not balanced
sub xyzzy : 5x5; # "5x5" not a valid identifier
sub plugh : Y2::north; # "Y2::north" not a simple identifier
sub snurt : foo + bar; # "+" not a colon or space
T h e a t t r i b u t e l i s t i s p a s s e d a s a l i s t o f c o n s t a n t s t r i n g s t o t h e c o d e w h i c h a s s o c i a t e s t h e m w i t h t h e s u b r o u t i n e . I n p a r t i c u l a r , t h e s e c o n d e x a m p l e o f v a l i d s y n t a x a b o v e c u r r e n t l y l o o k s l i k e t h i s i n t e r m s o f h o w i t ' s p a r s e d a n d i n v o k e d :
use attributes __PACKAGE__, \&plugh, q[Ugly('\(")], 'Bad';
F o r f u r t h e r d e t a i l s o n a t t r i b u t e l i s t s a n d t h e i r m a n i p u l a t i o n , s e e a t t r i b u t e s a n d A t t r i b u t e : : H a n d l e r s .
# S E E A L S O
S e e " F u n c t i o n T e m p l a t e s " i n p e r l r e f f o r m o r e a b o u t r e f e r e n c e s a n d c l o s u r e s . S e e p e r l x s i f y o u ' d l i k e t o l e a r n a b o u t c a l l i n g C s u b r o u t i n e s f r o m P e r l . S e e p e r l e m b e d i f y o u ' d l i k e t o l e a r n a b o u t c a l l i n g P e r l s u b r o u t i n e s f r o m C . S e e p e r l m o d t o l e a r n a b o u t b u n d l i n g u p y o u r f u n c t i o n s i n s e p a r a t e f i l e s . S e e p e r l m o d l i b t o l e a r n w h a t l i b r a r y m o d u l e s c o m e s t a n d a r d o n y o u r s y s t e m . S e e p e r l o o t u t t o l e a r n h o w t o m a k e o b j e c t m e t h o d c a l l s .
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 .