$纯量值 (scalar) (数字,字串或参考值 [reference])
    @阵列
    %杂凑阵列 (关连阵列)
    *代表同一个变数名的所有类形。在第四版中它们常用来达到指标
        (pointers)的功能,但现在在新版的 perl中这个角色已被参
考值 (reference)取代了。
虽然这些符号在某些场合下可省略,但建议你随处都用。
有些其他的符号你可能会碰到但却不是指定形态用的有:
    <>这是用来从一个档案把手 (filehandle)里输入一份记录
    \取某样东西的参考值 (reference)
注意 <
FILE>  不是用来指定档案的形态,亦非此把手的名字。它只是 
将<>这个运算子用在 
FILE这个把手上。在纯量的情境 (scalar context) 
下,它自 
FILE 
把手一次读入一行 
(嗯,该说一笔记录,参看
 
$/),在序列情境 (list context)下,则一次将 全部的内容读 
入。当对档案使用开、关或其它 <>之外的动作、或甚至只是提到把 
手时,切记不要使用 <>。下面的用法是正确的:eof(FH)
,
seek(FH, 0,2)
以及 ``copying from 
STDIN to 
FILE''。
use strict下则是必须的)。但由一个简单的字(不
能是一个已定义的副函数之名称)所构成的索引值,和 =>左端的运算子,都会被视为已纳入引号了:
这些是和这些一样的
    ------------            ---------------
    $foo{line}              $foo{"line"}
    bar => stuff            "bar" => stuff
一个区块末端的分号可有可无,一个序列的最後一个逗号亦同。良好的写作风格 (参看perlstyle)中建议除了在单行程式 (one-liners)的情况外都将他们加上去:
    if ($whoops) { exit 1 }
    @nums = (1, 2, 3);
    if ($whoops) {
        exit 1;
    }
    @lines = (
        "There Beren came from mountains cold",
        "And lost he wandered under leaves",
    );
$dir = (getpwnam($user))[7];
另一种方法就是在等号左端用 undef 作元素:
($dev, $ino, undef, undef, $uid, $gid) = stat($file);
$^W变数 (在 perlvar中有说明)控制一个区块在执行期 (runtime)的警告讯息:
    {
        local $^W = 0;        #暂时关掉警告讯息
        $a = $b + $c;         #我知道这些变数可能未定义
    }
注意,像所有的标点符号变数一样,目前不能对 $^W用 my,只能用 local()。
一个发展中的新 use warnings编译器指挥模组 (pragma) 
提供了更精细的控制。好奇宝宝们应该翻翻 perl5-porters
邮件论坛的档案库以获得更详细的说明。
一个常犯的错误像是:
unlink $file || die "snafu";
这会被解译器看成是:
unlink ($file || die "snafu");
要避免此问题,须加上括号或是用超低优先的 or运算子:
    (unlink $file) || die "snafu";
    unlink $file or die "snafu";
这些“英文的”运算子 (and, or, xor,及 not)是刻意设计成较一般序列运算子低的优先顺序,这就是为了解决前述的状况。
另一个拥有出人意料的优先顺序者为指数。它甚至高於负号,这使得 -2**2变成负四而非正四。他同时也会“向右靠”(right-associate),意思是说 
2**3**2 
代表二的九次方,而不是八的平方。
    $person = {};                   #新的不具名杂凑阵列
    $person->{AGE}  = 24;           #把 AGE栏的值设成 24
    $person->{NAME} = "Nat";        #将 NAME栏设成 "Nat"
如果你要的是更严谨的写法,看看 perltoot 。
下面是个方便的样板,你也许希望在撰写第一个模组时将他派上用场。记得要改名 字。
package Some::Module; #假设是 Some/Module.pm
use strict;
    BEGIN {
        use Exporter   ();
        use vars       qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
        ##设定版本以备版本检查之用;去掉 "#"号即可使用。
        ## $VERSION     = 1.00;
        #如果有使用 RCS/CVS,那应该考虑将下一行保留,
        #但是小心两位数版本编号可能造成的影响。
        $VERSION = do{my@r=q$Revision: 1.1 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r};
        @ISA         = qw(Exporter);
        @EXPORT      = qw(&func1 &func2 &func3);
        %EXPORT_TAGS = ( );     #例如: TAG => [ qw!name1 name2! ],
        #整个包裹要输出的全域变数(exported package globals)在此,
        #还有其他选择要输出的函数。
        @EXPORT_OK   = qw($Var1 %Hashit);
    }
    use vars      @EXPORT_OK;
    #没有输出的全域变数在此。
    use vars      qw( @more $stuff );
    #起始包裹内的全域变数,首先是要输出的那几个。
    $Var1   = '';
    %Hashit = ();
    #接下来是其他的 (还是能以 $Some::Module::stuff的方式撷取他们的值)
    $stuff  = '';
    @more   = ();
    #所有以档案为范围的变数名都
    #必须在让後面的函数使用前先创造出来。
    #以档案为范围的变数名在此。
    my $priv_var    = '';
    my %secret_hash = ();
    #下面是一个以档案为限的函数,当作一个闭包
    #可以用 &$priv_func的方式呼叫它;但不能使用原型定义
    my $priv_func = sub {
        #程式码放在这里
    };
    #不论是否要输出,都记得要将你的函数造出来。
    #别忘了在 {}括号间放些有趣的内容。
    sub func1      {}    #没有定义原型
    sub func2()    {}    #定原型为 void
    sub func3($$)  {}    #定原型为两个纯量值
    #这个函数虽然未被输出,但是可以被呼叫
    sub func4(\%)  {}    #定原型为一个杂凑阵列的参考值
    END { }       #模组清洁大队在此 (global destructor)
1; #模组必须传回真值
kill() 
没有将任何程序交给讯号):
    sub is_tainted {
        return ! eval { join('',@_), kill 0; 1; };
    }
然而,此方法会触发 -w参数的警告讯息。目前并无任何不会触发 -w的方法可下侦测变数污染 --
就把警告讯息当成是在提醒你,该把所有可能被污染的资料给 ``漂白''
(untaint)。
【译注:这里所提的 ``被污染'' (tainted),指的是当使用 -T这个参数时,或当 perl程式做 setuid或 setgid模式执行时 (在 UNIX 下), perl会自动将有安 全顾虑的变数列为受污染, 也就是 tainted。除非先做解除污染 (untaint)处理,否则 perl不会容许受污染的变数做出可能危害系统的举动。因此 CGI程式应尽可能地使用 -T这个参数以策安全。】
闭包 (closure)是个精确但又很难解释的电脑名词。在 Perl 里面,闭包是以 匿名函数的形式来实现,具有持续参照位於该函数范围之外的文字式变数值的能力。 这些外部的文字变数会神奇地保留它们在闭包函数最初定义时的值 (深连结)。
如果一个程式语言容许函数递回另一个函数的话 (像 Perl 就是),闭包便具有意 义。要注意的是,有些语言虽提供匿名函数的功能,但却无法正确处理闭包; Python 这个语言便是一例。如果要想多了解闭包的话,建议你去找本功能性程式 设计的教科书来看。Scheme这个语言不仅支援闭包,更鼓励多加使用。
以下是个典型的产生函数的函数:
    sub add_function_generator {
      return sub { shift + shift };
    }
    $add_sub = add_function_generator();
    $sum = &$add_sub(4,5);                # $sum现在是 9了
闭包用起来就像是个 函数样板,其中保留了一些可以在稍後再填入的空格。
add_function_generator()
所递回的匿名函数在技术上来讲并不能算是一个闭包,
因为它没有用到任何位在这个函数范围之外的文字变数。
把上面这个例子和下面这个 make_adder()函数对照一下,下面这个函数所递回的匿名函数中使用了一个外部的文字变数。这种指名外部函数的作法需要由 Perl递回一个适当的闭包,因此那个文字变数在匿名函数产生之时的值便永久地被锁进闭 
包里。
    sub make_adder {
        my $addpiece = shift;
        return sub { shift + $addpiece };
    }
    $f1 = make_adder(20);
    $f2 = make_adder(555);
这样一来 &$f1($n) 
永远会是 20加上你传进去的值 $n 
,而
&$f2($n) 
将 
永远会是 555加上你传进去的值 $n。$addpiece的值会在闭包中保留下来。
闭包在比较实际的场合中也常用得到,譬如当你想把一些程式码传入一个函数时:
    my $line;
    timeout( 30, sub { $line = <STDIN> } );
如果要执行的程式码当初是以字串的形式传入的话,即 '$line =
<STDIN>'
,那麽 timeout()
这个假想的函数在回到该函数被呼叫时所在的范围後便无法再撷取
$list这个文字变数的值了。
my() 
和 local()和闭包或 foreach()回圈变数及函数参数相互影响 
所致。
从前【在旧版 perl的时代】大家写程式的时候很容易因为这样而不小心把变数值 给弄丢。但现在 perl提供了一些保护措施,因此犯这种错的机率要小多了。
    my $f = "foo";
    sub T {
      while ($i++ < 3) { my $f = $f; $f .= "bar"; print $f, "\n" }
    }
    T;
    print "Finally $f\n";
有叁个 ``bar''加进去的 $f
变数应该是一个新的 $f (因为 my $f在每个回圈都应该创造一个新的区域变数)。然而,实际上并非如此。这个臭虫在未来的 perl 
版本中将会被修正。
func( \$some_scalar );
    func( \$some_array );
    func( [ 1 .. 10 ]   );
    func( \%some_hash   );
    func( { this => 10, that => 20 }   );
    func( \&some_func   );
    func( sub { $_[0] ** $_[1] }   );
*FH或 \*FH (这叫 ``typeglobs'' --请参看 perldata
),或是使用旧名 FileHandle的 IO::File模组以动态方式来产生档案把手亦可,这两个模组都附在标准 Perl 
版本内。
    use Fcntl;
    use IO::File;
    my $fh = new IO::File $filename, O_WRONLY|O_APPEND;
                or die "Can't append to $filename: $!";
    func($fh);
    sub compare($$) {
        my ($val1, $regexp) = @_;
        my $retval = eval { $val =~ /$regexp/ };
        die if $@;
        return $retval;
    }
    $match = compare("old McDonald", q/d.*D/);
确定绝对不要用以下的写法:
return eval "\$val =~ /$regexp/"; #错误
不然某人可以靠双引号括起来的字串以及 eval 双重解译的本质而偷偷插入 shell指令来作坏事。例如:
    $pattern_of_evil = 'danger ${ system("rm -rf * &") } danger';
eval "\$string =~ /$pattern_of_evil/";
想学非常非常聪明的方法的读者可以参考 O'Reilly 
出的 Mastering Regular
Expressions这本书,作者是 Jeffrey Friedl。其中第 273页的
Build_MatchMany_Function()特别的有趣。在 perlfaq2中可以找到有关本书 
的资料。
    call_a_lot(10, $some_obj, "methname")
    sub call_a_lot {
        my ($count, $widget, $trick) = @_;
        for (my $i = 0; $i < $count; $i++) {
            $widget->$trick();
        }
    }
不然你就用个闭包 (closure) 把物件和它的方法以及其参数都包在一起:
    my $whatnot =  sub { $some_obj->obfuscate(@args) };
    func($whatnot);
    sub func {
        my $code = shift;
        &$code();
    }
你也可以研究 
UNIVERSAL 
类别中的 can()方法 (附於标准 Perl 
版本中)。
以下就是实作函数私有变数的程式:
    BEGIN {
        my $counter = 42;
        sub prev_counter { return --$counter }
        sub next_counter { return $counter++ }
    }
prev_counter() 
和 next_counter()
将会共用一个於编译时起始的私有变数 $counter。
要宣告一个档案私有(file-private)变数,你仍然得使用
my(),将它放在档案开头处最外围。假设现在是在 Pax.pm
这个档案里:
    package Pax;
    my $started = scalar(localtime(time()));
    sub begun { return $started }
当用 use Pax或 require Pax载入此模组时,这个变数就会被起始。不过它不会被资源回收,像其他出了有效范围的变数那样,因为 begun()函数要用到它,但是没有其他函数能撷取它。这个变数不能以 $Pax::started 
的形式来撷取,因为它所存在的范围与此包裹无关。它存在的范围是这个档案。可想见地,一个档案里可以放好几个包裹,而所有的包裹都撷取同一个私有变数,但从另一个档案中,即使是属於同一个包裹(package),也不能取得它的值。
local($x) 
将全域变数 $x的原值存起来,并在此函数执行期间赋予一个新 
值,此值可以从此函数所呼叫的其他函数里看见。这整个步骤是在执行期间完成的,所以才叫做动态范围选取 (dynamic
scoping)。local()影响的是全域变数,或者称作包裹变数或动态变数。
my($x)会创造一个只能在目前这个函数里看得见的新变数。这个步骤是在编译
期完成(compile-time),所以称作文字式或是静态范围选取。my()总是作用在私
有变数,也称作文字式变数或(不当地)称作静态(范围选取)变数。
例如:
    sub visible {
        print "var has value $var\n";
    }
    sub dynamic {
        local $var = 'local';   #授予 $var这个全域变数
        visible();              #一个暂时的新值
    }
    sub lexical {
        my $var = 'private';    #新的私有变数,$var
        visible();              # (无法从此函数外看到)
    }
$var = 'global';
    visible();                  #会印出 global
    dynamic();                  #会印出 local
    lexical();                  #会印出 global
你可以发现在整个过程中 ``private''这个值都印不出来。那是因为
$var的值只存在於lexical()
函数的区块里面,对它所呼叫的函数来说是看不到的。
总结来说,local()不会产生你想像中的私有、区域变数。它只是将一个暂时的值
授予一个全域变数。如果你要的是私有的变数,那麽 my()
才是你要找的。
参看 perlsub ,里面有更详尽的解说。
use strict "refs"设定取掉。然後使用 ${'var'}
,而非 $var。
    local $var = "global";
    my    $var = "lexical";
print "lexical is $var\n";
    no strict 'refs';
    print "global  is ${'var'}\n";
如果你知道你所在的是哪一个包裹(package)的话,你可以直接指名,就像写
$Some_Pack::var这样。注意 $::var这个写法 并非表示目前此包裹 (package) 
内的动态变数 $var,而是指在 main包裹(package) 
里的那个,就等价於 $main::var。直接指定包裹(package)的名称虽然需要你把名字敲进程式码 
中,但是它执行起来比较快,也避免和
 use strict "refs" 
起冲突。
my()创造的)式的深连结。然而,动态变数(也称作全域(global),区域(local),或包裹(package)变数)在功效上是浅连结。就把这当作是少用它们的另一个理由好 
了。请参考
 闭包 (closure)是啥? 
一节。
local()会把 =号右边以序列情境来对待。而 <
FH>这个阅读的 
动作,就像 Perl里许多的函数以及运算子一样,会自动分辨出自己被呼叫时所在的情境并且采取适当的作法。一般来说,scalar()函数可以帮点忙。这个函数实际上对资料本身不会有任何作用(与一般所认为的相反),但是会告诉它所作用的函数要以对待纯量值的方法来运算。如果那个函数没有预先定义好碰到纯量情境的行为,那麽它当然也帮不了你(例如 sort() 
函数)。
然而,在以上这个例子 (local...)中,只要省略括号便可强制使用纯量情境:
    local($foo) = <FILE>;           #错误
    local($foo) = scalar(<FILE>);   #可以
    local $foo  = <FILE>;           #正确
其实在这个例子中,或许你该改用文字式变数 (lexical variables),不过会碰到 的问题跟上面一样:
    my($foo) = <FILE>;  #错误
    my $foo  = <FILE>;  #正确
如果你要覆盖掉某个内建函数,例如说 open(),那你得将其定义从另一个模组载 
入。参考
 Overriding Builtin Functions。在 
Class/Template里面也有个范例。
如果你要覆盖掉一个 Perl运算子,像是 +或 **
,那你该使用 use
overload这个编译器指挥模组(pragma),其文件在 overload
。
如果你要覆盖父类别 (parent class)里的方法呼叫 (method calls),请看 Overridden Methods 。
&foo的方式呼叫一个函数时,你等於让这个函数撷取你目前 @_里面的值,同时也跳过原型定义 (prototypes)不用。这表式此函数抓到的是你当时的 
@_, 
而非一个空的 
@_!虽然严格讲起来它也不能算是个 bug (但是在
 
perlsub里面是这麽说的)但在大部份情况下,这也算不上是个特别功能。
当你用 &foo()的方式呼叫你的函数时,你会得到一个新的 @_,但是原型定义 
仍然会被避开不用。
在一般情况下,你该用 foo()的方式去呼叫函数。只有在编译器已事先知道这
个函数的定义时,括号才能省略,譬如当这个函数所在的模组或包裹被 use
(但如果是被 require则不行)时,或是透过先前提及或 use subs宣告等
方法,让编译器先接触到这个函数的定义。用这种呼叫方式,即使是当括号省掉时,
你都会得到一个乾净的 @_,不会有任何不该出现的旧值残留在上面。
下面这个简单的 switch范例以模式对应为基础。我们将要做的是对储存在 
$whatchamacallit里面的参考值 (reference)的类型进行多重条件的判断。【译注:$whatchamacallit 
函意为 $what_you_might_call_it】
    SWITCH:
      for (ref $whatchamacallit) {
/^$/ && die '不是个参考值';
        /SCALAR/        && do {
                                print_scalar($$ref);
                                last SWITCH;
                        };
        /ARRAY/         && do {
                                print_array(@$ref);
                                last SWITCH;
                        };
        /HASH/          && do {
                                print_hash(%$ref);
                                last SWITCH;
                        };
        /CODE/          && do {
                                warn '无法印出函数的 ref';
                                last SWITCH;
                        };
# DEFAULT
warn '跳过使用者自定的类型';
}
如果是要处理一些在 -w之下触发警告讯息的未定义变数,你可以使用一个处理元 (handler)来捕捉 __WARN__这个虚拟信号 (pseudo-signal),范例如下:
    $SIG{__WARN__} = sub {
        for ( $_[0] ) {
            /Use of uninitialized value/  && do {
                #将警讯提升为致命行动
                die $_;
            };
#其它要捕捉的状况可以写在此。
            warn $_;
        }
};
print
ref($object)
来找出 $object这个物件是被归到哪个类别底下。
另一个可能的原因是你在 Perl还不知道这个包裹 (package)存在之前便将某个
类别名称在间接式物件语法中使用 (例如 find Guru "Samy")。最好是在开始使用你的包裹前,先确定都已经先把它们定义好了,如果你用的是 use 
而非 
require的话,这件事便会自动处理好。不然的话,确定你使用箭头式语法 (例如,Guru-find(``Samy'')>)。在perlobj 
里面对於物件的记号有详尽解释。
my $packname = ref bless [];
但如果是一个方法的话,而且印出的错误讯息中要包含呼叫此方法的物件 (不见得 就是把这个方法编译进去的那个物件)则:
    sub amethod {
        my $self = shift;
        my $class = ref($self) || $self;
        warn "我是被 $class这个物件所召唤";
    }
#这是程式
=for nobody 这段就变成了注解
#程式继续下去
=begin comment text
接下来此处所有
的文字都会被 所有人忽略
=end comment text
=cut
译者:陈彦铭、萧百龄
中译版着作权所有:陈彦铭、萧百龄及两只老虎工作室。 本中译版遵守并使用与原文版相同的使用条款发行。