Chapter 6 - Chapter 7
用Data::Dumper或YAML查看数据结构。
use YAML;
print Dump(\%some_hash);
用Storable存储数据结构到文件(store)、从文件中读取数据结构(retrieve)。
函数引用:
my %greets = (
Gilligan => \&gilligan_greets,
Skipper => \&skipper_greets,
Professor => \&professor_greets,
);
for my $person (qw(Skipper Gilligan)) {
$greets{$person}->('Professor');
}
闭包:In Perl terms, a closure is just a subroutine that references a lexical variable that has gone out of scope.
use File::Find;
my $callback;
{
my $count = 0;
$callback = sub { print ++$count, ": $File::Find::name\n" };
}
find($callback, '.');
可以通过$callback读取变量$count。
返回目录大小的闭包举例:
use File::Find;
sub create_find_callbacks_that_sum_the_size {
my $total_size = 0;
return(sub { $total_size += -s if -f }, sub { return $total_size });
}
my ($count_em, $get_results) = create_find_callbacks_that_sum_the_size( );
find($count_em, 'bin');
my $total_size = &$get_results( );
print "total size of bin is $total_size\n";
闭包是针对逻辑变量说di,具体:Closures are "closed" only on lexical variables, since lexical variables eventually go out of scope. Because a package variable (which is a global) never goes out of scope, a closure never closes on a package variable. All subroutines refer to the same single instance of the global variable.
Chapter 8
以标量初始化文件句柄:
open( my $fh, '>>', \$string_log )
or die "Could not append to string! $!";
用IO::File新建文件句柄,可建立临时文件。
用IO::Tee同时输出到两个句柄:
use IO::Tee;
$tee_fh = IO::Tee->new( $log_fh, $scalar_fh );
print $tee_fh "The radio works in the middle of the ocean!\n";
用IO::Tee从$read_fh读入,同时输出到$log_fh,$scalar_fh:
use IO::Tee;
$tee_fh = IO::Tee->new( $read_fh, $log_fh, $scalar_fh );
# reads from $read_fh
my $message = <$tee_fh>;
# prints to $log_fh and $scalar_fh
print $tee_fh $message;
读目录:
opendir my $dh, '.' or die "Could not open directory: $!";
foreach my $file ( readdir( $dh ) ) {
print "Skipper, I found $file!\n";
}
用IO::Dir读目录。
Chapter 9. Practical Reference Tricks
sort 之后array中各元素的位置:
my @input = qw(Gilligan Skipper Professor Ginger Mary_Ann);
my @sorted_positions = sort { $input[$a] cmp $input[$b] } 0..$#input;
my @ranks;
@ranks[@sorted_positions] = (1..@sorted_positions);
for (0..$#ranks) {
print "$input[$_] sorts into position $ranks[$_]\n";
}
Chapter 10. Building Larger Programs
do xxx.pm如同xxx.pm中的代码是嵌于当前程序中一般,但xxx.pm仍保持自身的范围,逻辑变量及use strict之类不会影响到当前程序。
require xxx.pm会先检查Perl是否已经读入过xxx.pm,每个文件只会读一次。如果xxx.pm中有语法错误,程序会直接die挂掉。xxx.pm最后返回的值必须为真。
临时添加目录到@INC:perl -I/home/skipper/perl-lib /home/skipper/bin/get_us_home
Chapter 11. Introduction to Objects
继承:
package Cow;
use base qw(Animal);
使用父类的函数:
{ package Animal;
sub speak {
my $class = shift;
print "a $class goes ", $class->sound, "!\n";
}
}
{ package Mouse;
@ISA = qw(Animal);
sub sound { 'squeak' }
sub speak {
my $class = shift;
$class-><span style="COLOR: #ff0000">SUPER::</span>speak;
print "[but you can barely hear it!]\n";
}
}
类函数调用:
my $beast = 'Class';
$beast->method(@args);
参数解析为('Class', @args),调用Class::method('Class', @args),如果没找到Class::method,就去Class的父类找。
用Data::Dumper或YAML查看数据结构。
use YAML;
print Dump(\%some_hash);
用Storable存储数据结构到文件(store)、从文件中读取数据结构(retrieve)。
函数引用:
my %greets = (
Gilligan => \&gilligan_greets,
Skipper => \&skipper_greets,
Professor => \&professor_greets,
);
for my $person (qw(Skipper Gilligan)) {
$greets{$person}->('Professor');
}
闭包:In Perl terms, a closure is just a subroutine that references a lexical variable that has gone out of scope.
use File::Find;
my $callback;
{
my $count = 0;
$callback = sub { print ++$count, ": $File::Find::name\n" };
}
find($callback, '.');
可以通过$callback读取变量$count。
返回目录大小的闭包举例:
use File::Find;
sub create_find_callbacks_that_sum_the_size {
my $total_size = 0;
return(sub { $total_size += -s if -f }, sub { return $total_size });
}
my ($count_em, $get_results) = create_find_callbacks_that_sum_the_size( );
find($count_em, 'bin');
my $total_size = &$get_results( );
print "total size of bin is $total_size\n";
闭包是针对逻辑变量说di,具体:Closures are "closed" only on lexical variables, since lexical variables eventually go out of scope. Because a package variable (which is a global) never goes out of scope, a closure never closes on a package variable. All subroutines refer to the same single instance of the global variable.
Chapter 8
以标量初始化文件句柄:
open( my $fh, '>>', \$string_log )
or die "Could not append to string! $!";
用IO::File新建文件句柄,可建立临时文件。
用IO::Tee同时输出到两个句柄:
use IO::Tee;
$tee_fh = IO::Tee->new( $log_fh, $scalar_fh );
print $tee_fh "The radio works in the middle of the ocean!\n";
用IO::Tee从$read_fh读入,同时输出到$log_fh,$scalar_fh:
use IO::Tee;
$tee_fh = IO::Tee->new( $read_fh, $log_fh, $scalar_fh );
# reads from $read_fh
my $message = <$tee_fh>;
# prints to $log_fh and $scalar_fh
print $tee_fh $message;
读目录:
opendir my $dh, '.' or die "Could not open directory: $!";
foreach my $file ( readdir( $dh ) ) {
print "Skipper, I found $file!\n";
}
用IO::Dir读目录。
Chapter 9. Practical Reference Tricks
sort 之后array中各元素的位置:
my @input = qw(Gilligan Skipper Professor Ginger Mary_Ann);
my @sorted_positions = sort { $input[$a] cmp $input[$b] } 0..$#input;
my @ranks;
@ranks[@sorted_positions] = (1..@sorted_positions);
for (0..$#ranks) {
print "$input[$_] sorts into position $ranks[$_]\n";
}
Chapter 10. Building Larger Programs
do xxx.pm如同xxx.pm中的代码是嵌于当前程序中一般,但xxx.pm仍保持自身的范围,逻辑变量及use strict之类不会影响到当前程序。
require xxx.pm会先检查Perl是否已经读入过xxx.pm,每个文件只会读一次。如果xxx.pm中有语法错误,程序会直接die挂掉。xxx.pm最后返回的值必须为真。
临时添加目录到@INC:perl -I/home/skipper/perl-lib /home/skipper/bin/get_us_home
Chapter 11. Introduction to Objects
继承:
package Cow;
use base qw(Animal);
使用父类的函数:
{ package Animal;
sub speak {
my $class = shift;
print "a $class goes ", $class->sound, "!\n";
}
}
{ package Mouse;
@ISA = qw(Animal);
sub sound { 'squeak' }
sub speak {
my $class = shift;
$class-><span style="COLOR: #ff0000">SUPER::</span>speak;
print "[but you can barely hear it!]\n";
}
}
类函数调用:
my $beast = 'Class';
$beast->method(@args);
参数解析为('Class', @args),调用Class::method('Class', @args),如果没找到Class::method,就去Class的父类找。
Chapter 12-15
限制函数只能通过Class名/实例访问:
弱引用(use WeakRef;),不增加引用对象的引用计数值,在引用计数变0时,弱引用会自动变undef。例子见13.7. Weakening the Argument。
检查实例是否属于某个类: $tv_horse->isa('Animal')
检查是否存在指定的类函数:
Class::MethodMaker和Class::Accessor帮助快速指定类属性,并生成类函数。
使用Exporter指定导出的函数:
还有 %EXPORT_TAGS可以将函数分类。
use Carp qw(croak); sub instance_only { ref(my $self = shift) or croak "instance variable needed"; ... use $self as the instance ... } sub class_only { ref(my $class = shift) and croak "class name needed"; ... use $class as the class ... }记得在析构函数中调用$self->SUPER::DESTROY
弱引用(use WeakRef;),不增加引用对象的引用计数值,在引用计数变0时,弱引用会自动变undef。例子见13.7. Weakening the Argument。
检查实例是否属于某个类: $tv_horse->isa('Animal')
检查是否存在指定的类函数:
if ($tv_horse->can('eat')) { $tv_horse->eat('hay'); }如果$self->some_method()找不到,就搜UNIVERSAL::some_method(),还找不到,就搜AUTOLOAD()。
Class::MethodMaker和Class::Accessor帮助快速指定类属性,并生成类函数。
使用Exporter指定导出的函数:
package Navigate::SeatOfPants; our @EXPORT = qw(guess_direction_toward); our @EXPORT_OK = qw(ask_the_skipper_about get_north_from_professor); use base qw(Exporter);其中,@EXPORT指定use Navigate::SeatOfPants;时可用的函数,@EXPORT_OK指定Navigate::SeatOfPants qw/xxx yyy zzz/时可用的函数。
还有 %EXPORT_TAGS可以将函数分类。
Chapter 16-19
使用Module::Starter及Module::Build建立Perl模块。
使用Test::More进行测试,tests指定跑几次测试。
cpan> readme Island::Plotting::Maps 看一个模块的说明。写pod,大概就是=head1,=over,=item之类。
使用Test::More进行测试,tests指定跑几次测试。
use Test::More tests => 9; { $n = -1; eval { sqrt($n) }; ok( $@, '$@ is set after sqrt(-1)' ); } 测试相关模块Test::Harness、 Test::Manifest、Test::MockObject等。
测试pod文档的模块Test::Pod。
分支测试Devel::Cover。
自定义测试Test::Builder。
没有评论:
发表评论