⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switch.pm

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 PM
📖 第 1 页 / 共 2 页
字号:
		my $lop = ref $left eq 'Switch'			? $left			: bless { arity=>0, impl=>sub{$left} };		my $arity = $lop->{arity};		return bless {				arity => $arity,				impl  => sub { $op->($lop->{impl}->(@_)) }			     };	};}use overload	"+"	=> 	meta_bop {$_[0] + $_[1]},	"-"	=> 	meta_bop {$_[0] - $_[1]},  	"*"	=>  	meta_bop {$_[0] * $_[1]},	"/"	=>  	meta_bop {$_[0] / $_[1]},	"%"	=>  	meta_bop {$_[0] % $_[1]},	"**"	=>  	meta_bop {$_[0] ** $_[1]},	"<<"	=>  	meta_bop {$_[0] << $_[1]},	">>"	=>  	meta_bop {$_[0] >> $_[1]},	"x"	=>  	meta_bop {$_[0] x $_[1]},	"."	=>  	meta_bop {$_[0] . $_[1]},	"<"	=>  	meta_bop {$_[0] < $_[1]},	"<="	=>  	meta_bop {$_[0] <= $_[1]},	">"	=>  	meta_bop {$_[0] > $_[1]},	">="	=>  	meta_bop {$_[0] >= $_[1]},	"=="	=>  	meta_bop {$_[0] == $_[1]},	"!="	=>  	meta_bop {$_[0] != $_[1]},	"<=>"	=>  	meta_bop {$_[0] <=> $_[1]},	"lt"	=>  	meta_bop {$_[0] lt $_[1]},	"le"	=> 	meta_bop {$_[0] le $_[1]},	"gt"	=> 	meta_bop {$_[0] gt $_[1]},	"ge"	=> 	meta_bop {$_[0] ge $_[1]},	"eq"	=> 	meta_bop {$_[0] eq $_[1]},	"ne"	=> 	meta_bop {$_[0] ne $_[1]},	"cmp"	=> 	meta_bop {$_[0] cmp $_[1]},	"\&"	=> 	meta_bop {$_[0] & $_[1]},	"^"	=> 	meta_bop {$_[0] ^ $_[1]},	"|"	=>	meta_bop {$_[0] | $_[1]},	"atan2"	=>	meta_bop {atan2 $_[0], $_[1]},	"neg"	=>	meta_uop {-$_[0]},	"!"	=>	meta_uop {!$_[0]},	"~"	=>	meta_uop {~$_[0]},	"cos"	=>	meta_uop {cos $_[0]},	"sin"	=>	meta_uop {sin $_[0]},	"exp"	=>	meta_uop {exp $_[0]},	"abs"	=>	meta_uop {abs $_[0]},	"log"	=>	meta_uop {log $_[0]},	"sqrt"  =>	meta_uop {sqrt $_[0]},	"bool"  =>	sub { croak "Can't use && or || in expression containing __" },	#	"&()"	=>	sub { $_[0]->{impl} },	#	"||"	=>	meta_bop {$_[0] || $_[1]},	#	"&&"	=>	meta_bop {$_[0] && $_[1]},	# fallback => 1,	;1;__END__=head1 NAMESwitch - A switch statement for Perl=head1 VERSIONThis document describes version 2.11 of Switch,released Nov 22, 2006.=head1 SYNOPSIS    use Switch;    switch ($val) {	case 1		{ print "number 1" }	case "a"	{ print "string a" }	case [1..10,42]	{ print "number in list" }	case (@array)	{ print "number in list" }	case /\w+/	{ print "pattern" }	case qr/\w+/	{ print "pattern" }	case (%hash)	{ print "entry in hash" }	case (\%hash)	{ print "entry in hash" }	case (\&sub)	{ print "arg to subroutine" }	else		{ print "previous case not true" }    }=head1 BACKGROUND[Skip ahead to L<"DESCRIPTION"> if you don't care about the whysand wherefores of this control structure]In seeking to devise a "Swiss Army" case mechanism suitable for Perl,it is useful to generalize this notion of distributed conditionaltesting as far as possible. Specifically, the concept of "matching"between the switch value and the various case values need not berestricted to numeric (or string or referential) equality, as it is in other languages. Indeed, as Table 1 illustrates, Perloffers at least eighteen different ways in which two values couldgenerate a match.	Table 1: Matching a switch value ($s) with a case value ($c)        Switch  Case    Type of Match Implied   Matching Code        Value   Value           ======  =====   =====================   =============        number  same    numeric or referential  match if $s == $c;        or ref          equality	object  method	result of method call   match if $s->$c();	ref     name 				match if defined $s->$c();		or ref        other   other   string equality         match if $s eq $c;        non-ref non-ref        scalar  scalar        string  regexp  pattern match           match if $s =~ /$c/;        array   scalar  array entry existence   match if 0<=$c && $c<@$s;        ref             array entry definition  match if defined $s->[$c];                        array entry truth       match if $s->[$c];        array   array   array intersection      match if intersects(@$s, @$c);        ref     ref     (apply this table to                         all pairs of elements                         $s->[$i] and                         $c->[$j])        array   regexp  array grep              match if grep /$c/, @$s;        ref             hash    scalar  hash entry existence    match if exists $s->{$c};        ref             hash entry definition   match if defined $s->{$c};                        hash entry truth        match if $s->{$c};        hash    regexp  hash grep               match if grep /$c/, keys %$s;        ref             sub     scalar  return value defn       match if defined $s->($c);        ref             return value truth      match if $s->($c);        sub     array   return value defn       match if defined $s->(@$c);        ref     ref     return value truth      match if $s->(@$c);In reality, Table 1 covers 31 alternatives, because only the equality andintersection tests are commutative; in all other cases, the roles ofthe C<$s> and C<$c> variables could be reversed to produce adifferent test. For example, instead of testing a single hash forthe existence of a series of keys (C<match if exists $s-E<gt>{$c}>),one could test for the existence of a single key in a series of hashes(C<match if exists $c-E<gt>{$s}>).=head1 DESCRIPTIONThe Switch.pm module implements a generalized case mechanism that coversmost (but not all) of the numerous possible combinations of switch and casevalues described above.The module augments the standard Perl syntax with two new controlstatements: C<switch> and C<case>. The C<switch> statement takes asingle scalar argument of any type, specified in parentheses.C<switch> stores this value as thecurrent switch value in a (localized) control variable.The value is followed by a block which may contain one or morePerl statements (including the C<case> statement described below).The block is unconditionally executed once the switch value hasbeen cached.A C<case> statement takes a single scalar argument (in mandatoryparentheses if it's a variable; otherwise the parens are optional) andselects the appropriate type of matching between that argument and thecurrent switch value. The type of matching used is determined by therespective types of the switch value and the C<case> argument, asspecified in Table 1. If the match is successful, the mandatoryblock associated with the C<case> statement is executed.In most other respects, the C<case> statement is semantically identicalto an C<if> statement. For example, it can be followed by an C<else>clause, and can be used as a postfix statement qualifier. However, when a C<case> block has been executed control is automaticallytransferred to the statement after the immediately enclosing C<switch>block, rather than to the next statement within the block. In otherwords, the success of any C<case> statement prevents other cases in thesame scope from executing. But see L<"Allowing fall-through"> below.Together these two new statements provide a fully generalized casemechanism:        use Switch;        # AND LATER...        %special = ( woohoo => 1,  d'oh => 1 );        while (<>) {	    chomp;            switch ($_) {                case (%special) { print "homer\n"; }      # if $special{$_}                case /[a-z]/i   { print "alpha\n"; }      # if $_ =~ /a-z/i                case [1..9]     { print "small num\n"; }  # if $_ in [1..9]                case { $_[0] >= 10 } { print "big num\n"; } # if $_ >= 10                print "must be punctuation\n" case /\W/;  # if $_ ~= /\W/	    }        }Note that C<switch>es can be nested within C<case> (or any other) blocks,and a series of C<case> statements can try different types of matches-- hash membership, pattern match, array intersection, simple equality,etc. -- against the same switch value.The use of intersection tests against an array reference is particularlyuseful for aggregating integral cases:        sub classify_digit        {                switch ($_[0]) { case 0            { return 'zero' }                                 case [2,4,6,8]    { return 'even' }                                 case [1,3,5,7,9]  { return 'odd' }                                 case /[A-F]/i     { return 'hex' }                               }        }=head2 Allowing fall-throughFall-though (trying another case after one has already succeeded)is usually a Bad Idea in a switch statement. However, thisis Perl, not a police state, so there I<is> a way to do it, if you must.If a C<case> block executes an untargeted C<next>, control isimmediately transferred to the statement I<after> the C<case> statement(i.e. usually another case), rather than out of the surroundingC<switch> block.For example:        switch ($val) {                case 1      { handle_num_1(); next }    # and try next case...                case "1"    { handle_str_1(); next }    # and try next case...                case [0..9] { handle_num_any(); }       # and we're done                case /\d/   { handle_dig_any(); next }  # and try next case...                case /.*/   { handle_str_any(); next }  # and try next case...        }If $val held the number C<1>, the above C<switch> block would call thefirst three C<handle_...> subroutines, jumping to the next case testeach time it encountered a C<next>. After the third C<case> blockwas executed, control would jump to the end of the enclosingC<switch> block.On the other hand, if $val held C<10>, then only the last two C<handle_...>subroutines would be called.Note that this mechanism allows the notion of I<conditional fall-through>.For example:        switch ($val) {                case [0..9] { handle_num_any(); next if $val < 7; }                case /\d/   { handle_dig_any(); }        }If an untargeted C<last> statement is executed in a case block, thisimmediately transfers control out of the enclosing C<switch> block(in other words, there is an implicit C<last> at the end of eachnormal C<case> block). Thus the previous example could also have beenwritten:        switch ($val) {                case [0..9] { handle_num_any(); last if $val >= 7; next; }                case /\d/   { handle_dig_any(); }        }=head2 Automating fall-throughIn situations where case fall-through should be the norm, rather than anexception, an endless succession of terminal C<next>s is tedious and ugly.Hence, it is possible to reverse the default behaviour by specifyingthe string "fallthrough" when importing the module. For example, the following code is equivalent to the first example in L<"Allowing fall-through">:        use Switch 'fallthrough';        switch ($val) {                case 1      { handle_num_1(); }                case "1"    { handle_str_1(); }                case [0..9] { handle_num_any(); last }                case /\d/   { handle_dig_any(); }                case /.*/   { handle_str_any(); }        }Note the explicit use of a C<last> to preserve the non-fall-throughbehaviour of the third case.=head2 Alternative syntaxPerl 6 will provide a built-in switch statement with essentially thesame semantics as those offered by Switch.pm, but with a differentpair of keywords. In Perl 6 C<switch> will be spelled C<given>, andC<case> will be pronounced C<when>. In addition, the C<when> statementwill not require switch or case values to be parenthesized.This future syntax is also (largely) available via the Switch.pm module, byimporting it with the argument C<"Perl6">.  For example:        use Switch 'Perl6';        given ($val) {                when 1       { handle_num_1(); }                when ($str1) { handle_str_1(); }                when [0..9]  { handle_num_any(); last }                when /\d/    { handle_dig_any(); }                when /.*/    { handle_str_any(); }                default      { handle anything else; }        }Note that scalars still need to be parenthesized, since they would beambiguous in Perl 5.Note too that you can mix and match both syntaxes by importing the modulewith:	use Switch 'Perl5', 'Perl6';=head2 Higher-order OperationsOne situation in which C<switch> and C<case> do not provide a goodsubstitute for a cascaded C<if>, is where a switch value needs tobe tested against a series of conditions. For example:        sub beverage {            switch (shift) {                case { $_[0] < 10 } { return 'milk' }                case { $_[0] < 20 } { return 'coke' }                case { $_[0] < 30 } { return 'beer' }                case { $_[0] < 40 } { return 'wine' }                case { $_[0] < 50 } { return 'malt' }                case { $_[0] < 60 } { return 'Moet' }                else                { return 'milk' }            }        }(This is equivalent to writing C<case (sub { $_[0] < 10 })>, etc.; C<$_[0]>is the argument to the anonymous subroutine.)The need to specify each condition as a subroutine block is tiresome. Toovercome this, when importing Switch.pm, a special "placeholder"subroutine named C<__> [sic] may also be imported. This subroutineconverts (almost) any expression in which it appears to a reference to ahigher-order function. That is, the expression:        use Switch '__';        __ < 2is equivalent to:        sub { $_[0] < 2 }With C<__>, the previous ugly case statements can be rewritten:        case  __ < 10  { return 'milk' }        case  __ < 20  { return 'coke' }        case  __ < 30  { return 'beer' }        case  __ < 40  { return 'wine' }        case  __ < 50  { return 'malt' }        case  __ < 60  { return 'Moet' }        else           { return 'milk' }The C<__> subroutine makes extensive use of operator overloading toperform its magic. All operations involving __ are overloaded toproduce an anonymous subroutine that implements a lazy versionof the original operation.The only problem is that operator overloading does not allow theboolean operators C<&&> and C<||> to be overloaded. So a case statementlike this:        case  0 <= __ && __ < 10  { return 'digit' }  doesn't act as expected, because when it isexecuted, it constructs two higher order subroutinesand then treats the two resulting references as arguments to C<&&>:        sub { 0 <= $_[0] } && sub { $_[0] < 10 }This boolean expression is inevitably true, since both references arenon-false. Fortunately, the overloaded C<'bool'> operator catches thissituation and flags it as a error. =head1 DEPENDENCIESThe module is implemented using Filter::Util::Call and Text::Balancedand requires both these modules to be installed. =head1 AUTHORDamian Conway (damian@conway.org). The maintainer of this module is now RafaelGarcia-Suarez (rgarciasuarez@gmail.com).=head1 BUGSThere are undoubtedly serious bugs lurking somewhere in code this funky :-)Bug reports and other feedback are most welcome.=head1 LIMITATIONSDue to the heuristic nature of Switch.pm's source parsing, the presence ofregexes with embedded newlines that are specified with raw C</.../>delimiters and don't have a modifier C<//x> are indistinguishable fromcode chunks beginning with the division operator C</>. As a workaroundyou must use C<m/.../> or C<m?...?> for such patterns. Also, the presenceof regexes specified with raw C<?...?> delimiters may cause mysteriouserrors. The workaround is to use C<m?...?> instead.Due to the way source filters work in Perl, you can't use Switch insidean string C<eval>.If your source file is longer then 1 million characters and you have aswitch statement that crosses the 1 million (or 2 million, etc.)character boundary you will get mysterious errors. The workaround is touse smaller source files.=head1 COPYRIGHT    Copyright (c) 1997-2006, Damian Conway. All Rights Reserved.    This module is free software. It may be used, redistributed        and/or modified under the same terms as Perl itself.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -