#!/usr/bin/perl package Wrap::Simple; use warnings; use strict 'vars'; use Exporter; use vars qw/$VERSION @ISA @EXPORT @EXPORT_OK/; $VERSION = "1.0"; $VERSION = eval $VERSION; @ISA = qw/Exporter/; @EXPORT = qw/can wrap/; @EXPORT_OK = @EXPORT; =pod =head1 NAME Wrap::Simple - a simple wrapper for perl =head1 INTERFACES =over 4 =item can B 用来检测传递的参数是否可执行,如果可执行则返回该函数引用。参数分为两种,一为函数名, 此时通过检测 main 包中的符号表来检测是否可执行。另外一种方式为代码引用,此时通过 B 方式来检测。 sub foo { print "foo ...\n" } my $p1 = 'foo'; my $p2 = \&foo; print can $p1; print can $p2; =cut sub can { my $func = shift; return $func if $func and ref $func eq 'CODE'; if (grep { $_ eq $func } keys %::) { *f = $::{$func}; return \&f; } return 0; } =item wrap B 用来封装函数并返回函数引用。第一个参数为要封装的函数,剩余的参数为封装列表。 修饰符暂时只有 pre 和 post。 sub foo1 { ... } sub foo2 { ... } sub foo3 { ... } sub foo4 { ... } my $ref = wrap 'foo', pre=>\&foo1, pre=>\&foo2, pre=>'foo3', post=>\&foo4; $ref->("Hello World"); =cut sub wrap { my $func = shift; my $funp = can $func; my @pre_funcs = (); my @post_funcs = (); die "$func unvalid!" unless ref $funp eq 'CODE'; die "@_ unvalid. Perhaps not be in pair." if scalar(@_)%2; while (@_) { my $p1 = shift; my $p2 = shift; my $pf = can $p2; die "$p2 unvalid!" unless ref $pf eq 'CODE'; if ($p1 eq 'pre') { push @pre_funcs, $pf; } elsif ($p1 eq 'post') { push @post_funcs, $pf; } else { die "$p1 delegation error!"; } } return sub { my $param = shift; map $_->(), @pre_funcs; $func->($param); map $_->(), @post_funcs; } } =back =head1 EXAMPLE sub core { print "core function with param ",shift, "\n" } sub foo1 { print "foo1\n" } sub foo2 { print "foo2\n" } sub foo3 { print "foo3\n" } sub foo4 { print "foo4\n" } my $ref = wrap 'core', pre=>'foo1', pre=>\&foo2, pre=>\&foo3, post=>\&foo4; $ref->('Hello World'); =head1 LOG =over 4 =item Mon Feb 6 22:06:42 HKT 2012 模块外与模块内符号表混乱,需要进一步FIX。当使用函数名而不是函数引用时,会发生 该类问题。 FIXED。需要通过%::哈希表来得到具体的符号表,然后形成相应的引用。 =back =head1 AUTHOR xiaomo(wxm4ever@gmail.com) =cut 1; __END__