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

📄 overload.pm

📁 MSYS在windows下模拟了一个类unix的终端
💻 PM
📖 第 1 页 / 共 3 页
字号:
=head1 SPECIAL SYMBOLS FOR C<use overload>Three keys are recognized by Perl that are not covered by the abovedescription.=head2 Last ResortC<"nomethod"> should be followed by a reference to a function of fourparameters.  If defined, it is called when the overloading mechanismcannot find a method for some operation.  The first three arguments ofthis function coincide with the arguments for the corresponding method ifit were found, the fourth argument is the symbolcorresponding to the missing method.  If several methods are tried,the last one is used.  Say, C<1-$a> can be equivalent to	&nomethodMethod($a,1,1,"-")if the pair C<"nomethod" =E<gt> "nomethodMethod"> was specified in theC<use overload> directive.The C<"nomethod"> mechanism is I<not> used for the dereference operators( ${} @{} %{} &{} *{} ).If some operation cannot be resolved, and there is no functionassigned to C<"nomethod">, then an exception will be raised via die()--unless C<"fallback"> was specified as a key in C<use overload> directive.=head2 FallbackThe key C<"fallback"> governs what to do if a method for a particularoperation is not found.  Three different cases are possible depending onthe value of C<"fallback">:=over 16=item * C<undef>Perl tries to use asubstituted method (see L<MAGIC AUTOGENERATION>).  If this fails, itthen tries to calls C<"nomethod"> value; if missing, an exceptionwill be raised.=item * TRUEThe same as for the C<undef> value, but no exception is raised.  Instead,it silently reverts to what it would have done were there no C<use overload>present.=item * defined, but FALSENo autogeneration is tried.  Perl tries to callC<"nomethod"> value, and if this is missing, raises an exception.=backB<Note.> C<"fallback"> inheritance via @ISA is not carved in stoneyet, see L<"Inheritance and overloading">.=head2 Copy ConstructorThe value for C<"="> is a reference to a function with threearguments, i.e., it looks like the other values in C<useoverload>. However, it does not overload the Perl assignmentoperator. This would go against Camel hair.This operation is called in the situations when a mutator is appliedto a reference that shares its object with some other reference, suchas	$a=$b;	++$a;To make this change $a and not change $b, a copy of C<$$a> is made,and $a is assigned a reference to this new object.  This operation isdone during execution of the C<++$a>, and not during the assignment,(so before the increment C<$$a> coincides with C<$$b>).  This is onlydone if C<++> is expressed via a method for C<'++'> or C<'+='> (orC<nomethod>).  Note that if this operation is expressed via C<'+'>a nonmutator, i.e., as in	$a=$b;	$a=$a+1;then C<$a> does not reference a new copy of C<$$a>, since $$a does notappear as lvalue when the above code is executed.If the copy constructor is required during the execution of some mutator,but a method for C<'='> was not specified, it can be autogenerated as astring copy if the object is a plain scalar.=over 5=item B<Example>The actually executed code for	$a=$b;        Something else which does not modify $a or $b....	++$a;may be	$a=$b;        Something else which does not modify $a or $b....	$a = $a->clone(undef,"");        $a->incr(undef,"");if $b was mathemagical, and C<'++'> was overloaded with C<\&incr>,C<'='> was overloaded with C<\&clone>.=backSame behaviour is triggered by C<$b = $a++>, which is consider a synonym forC<$b = $a; ++$a>.=head1 MAGIC AUTOGENERATIONIf a method for an operation is not found, and the value for  C<"fallback"> isTRUE or undefined, Perl tries to autogenerate a substitute method forthe missing operation based on the defined operations.  Autogenerated methodsubstitutions are possible for the following operations:=over 16=item I<Assignment forms of arithmetic operations>C<$a+=$b> can use the method for C<"+"> if the method for C<"+=">is not defined.=item I<Conversion operations>String, numeric, and boolean conversion are calculated in terms of oneanother if not all of them are defined.=item I<Increment and decrement>The C<++$a> operation can be expressed in terms of C<$a+=1> or C<$a+1>,and C<$a--> in terms of C<$a-=1> and C<$a-1>.=item C<abs($a)>can be expressed in terms of C<$aE<lt>0> and C<-$a> (or C<0-$a>).=item I<Unary minus>can be expressed in terms of subtraction.=item I<Negation>C<!> and C<not> can be expressed in terms of boolean conversion, orstring or numerical conversion.=item I<Concatenation>can be expressed in terms of string conversion.=item I<Comparison operations>can be expressed in terms of its "spaceship" counterpart: eitherC<E<lt>=E<gt>> or C<cmp>:    <, >, <=, >=, ==, != 	in terms of <=>    lt, gt, le, ge, eq, ne 	in terms of cmp=item I<Iterator>    <>				in terms of builtin operations=item I<Dereferencing>    ${} @{} %{} &{} *{}		in terms of builtin operations=item I<Copy operator>can be expressed in terms of an assignment to the dereferenced value, if thisvalue is a scalar and not a reference.=back=head1 Losing overloadingThe restriction for the comparison operation is that even if, for example,`C<cmp>' should return a blessed reference, the autogenerated `C<lt>'function will produce only a standard logical value based on thenumerical value of the result of `C<cmp>'.  In particular, a workingnumeric conversion is needed in this case (possibly expressed in terms ofother conversions).Similarly, C<.=>  and C<x=> operators lose their mathemagical propertiesif the string conversion substitution is applied.When you chop() a mathemagical object it is promoted to a string and itsmathemagical properties are lost.  The same can happen with otheroperations as well.=head1 Run-time OverloadingSince all C<use> directives are executed at compile-time, the only way tochange overloading during run-time is to    eval 'use overload "+" => \&addmethod';You can also use    eval 'no overload "+", "--", "<="';though the use of these constructs during run-time is questionable.=head1 Public functionsPackage C<overload.pm> provides the following public functions:=over 5=item overload::StrVal(arg)Gives string value of C<arg> as in absence of stringify overloading.=item overload::Overloaded(arg)Returns true if C<arg> is subject to overloading of some operations.=item overload::Method(obj,op)Returns C<undef> or a reference to the method that implements C<op>.=back=head1 Overloading constantsFor some application Perl parser mangles constants too much.  It is possibleto hook into this process via overload::constant() and overload::remove_constant()functions.These functions take a hash as an argument.  The recognized keys of this hashare=over 8=item integerto overload integer constants,=item floatto overload floating point constants,=item binaryto overload octal and hexadecimal constants,=item qto overload C<q>-quoted strings, constant pieces of C<qq>- and C<qx>-quotedstrings and here-documents,=item qrto overload constant pieces of regular expressions.=backThe corresponding values are references to functions which take three arguments:the first one is the I<initial> string form of the constant, the second oneis how Perl interprets this constant, the third one is how the constant is used.Note that the initial string form does notcontain string delimiters, and has backslashes in backslash-delimitercombinations stripped (thus the value of delimiter is not relevant forprocessing of this string).  The return value of this function is how thisconstant is going to be interpreted by Perl.  The third argument is undefinedunless for overloaded C<q>- and C<qr>- constants, it is C<q> in single-quotecontext (comes from strings, regular expressions, and single-quote HEREdocuments), it is C<tr> for arguments of C<tr>/C<y> operators,it is C<s> for right-hand side of C<s>-operator, and it is C<qq> otherwise.Since an expression C<"ab$cd,,"> is just a shortcut for C<'ab' . $cd . ',,'>,it is expected that overloaded constant strings are equipped with reasonableoverloaded catenation operator, otherwise absurd results will result.Similarly, negative numbers are considered as negations of positive constants.Note that it is probably meaningless to call the functions overload::constant()and overload::remove_constant() from anywhere but import() and unimport() methods.From these methods they may be called as	sub import {	  shift;	  return unless @_;	  die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant';	  overload::constant integer => sub {Math::BigInt->new(shift)};	}B<BUGS> Currently overloaded-ness of constants does not propagateinto C<eval '...'>.=head1 IMPLEMENTATIONWhat follows is subject to change RSN.The table of methods for all operations is cached in magic for thesymbol table hash for the package.  The cache is invalidated duringprocessing of C<use overload>, C<no overload>, new functiondefinitions, and changes in @ISA. However, this invalidation remainsunprocessed until the next C<bless>ing into the package. Hence if youwant to change overloading structure dynamically, you'll need anadditional (fake) C<bless>ing to update the table.(Every SVish thing has a magic queue, and magic is an entry in thatqueue.  This is how a single variable may participate in multipleforms of magic simultaneously.  For instance, environment variablesregularly have two forms at once: their %ENV magic and their taintmagic. However, the magic which implements overloading is applied tothe stashes, which are rarely used directly, thus should not slow downPerl.)If an object belongs to a package using overload, it carries a specialflag.  Thus the only speed penalty during arithmetic operations withoutoverloading is the checking of this flag.In fact, if C<use overload> is not present, there is almost no overheadfor overloadable operations, so most programs should not suffermeasurable performance penalties.  A considerable effort was made tominimize the overhead when overload is used in some package, but thearguments in question do not belong to packages using overload.  Whenin doubt, test your speed with C<use overload> and without it.  So farthere have been no reports of substantial speed degradation if Perl iscompiled with optimization turned on.There is no size penalty for data if overload is not used. The onlysize penalty if overload is used in some package is that I<all> thepackages acquire a magic during the next C<bless>ing into thepackage. This magic is three-words-long for packages withoutoverloading, and carries the cache table if the package is overloaded.Copying (C<$a=$b>) is shallow; however, a one-level-deep copying iscarried out before any operation that can imply an assignment to theobject $a (or $b) refers to, like C<$a++>.  You can override thisbehavior by defining your own copy constructor (see L<"Copy Constructor">).It is expected that arguments to methods that are not explicitly supposedto be changed are constant (but this is not enforced).=head1 Metaphor clashOne may wonder why the semantic of overloaded C<=> is so counter intuitive.If it I<looks> counter intuitive to you, you are subject to a metaphorclash.Here is a Perl object metaphor:I<  object is a reference to blessed data>and an arithmetic metaphor:I<  object is a thing by itself>.The I<main> problem of overloading C<=> is the fact that these metaphorsimply different actions on the assignment C<$a = $b> if $a and $b areobjects.  Perl-think implies that $a becomes a reference to whatever$b was referencing.  Arithmetic-think implies that the value of "object"$a is changed to become the value of the object $b, preserving the factthat $a and $b are separate entities.The difference is not relevant in the absence of mutators.  Aftera Perl-way assignment an operation which mutates the data referenced by $awould change the data referenced by $b too.  Effectively, afterC<$a = $b> values of $a and $b become I<indistinguishable>.On the other hand, anyone who has used algebraic notation knows theexpressive power of the arithmetic metaphor.  Overloading works hardto enable this metaphor while preserving the Perlian way as far aspossible.  Since it is not not possible to freely mix two contradictingmetaphors, overloading allows the arithmetic way to write things I<asfar as all the mutators are called via overloaded access only>.  Theway it is done is described in L<Copy Constructor>.If some mutator methods are directly applied to the overloaded values,one may need to I<explicitly unlink> other values which references thesame value:    $a = new Data 23;    ...    $b = $a;		# $b is "linked" to $a    ...    $a = $a->clone;	# Unlink $b from $a    $a->increment_by(4);Note that overloaded access makes this transparent:    $a = new Data 23;    $b = $a;		# $b is "linked" to $a    $a += 4;		# would unlink $b automagicallyHowever, it would not make    $a = new Data 23;    $a = 4;		# Now $a is a plain 4, not 'Data'preserve "objectness" of $a.  But Perl I<has> a way to make assignmentsto an object do whatever you want.  It is just not the overload, buttie()ing interface (see L<perlfunc/tie>).  Adding a FETCH() methodwhich returns the object itself, and STORE() method which changes thevalue of the object, one can reproduce the arithmetic metaphor in itscompleteness, at least for variables which were tie()d from the start.(Note that a workaround for a bug may be needed, see L<"BUGS">.)=head1 CookbookPlease add examples to what follows!=head2 Two-face scalarsPut this in F<two_face.pm> in your Perl library directory:  package two_face;		# Scalars with separate string and                                # numeric values.  sub new { my $p = shift; bless [@_], $p }  use overload '""' => \&str, '0+' => \&num, fallback => 1;  sub num {shift->[1]}  sub str {shift->[0]}Use it as follows:  require two_face;  my $seven = new two_face ("vii", 7);  printf "seven=$seven, seven=%d, eight=%d\n", $seven, $seven+1;  print "seven contains `i'\n" if $seven =~ /i/;(The second line creates a scalar which has both a string value, and anumeric value.)  This prints:  seven=vii, seven=7, eight=8  seven contains `i'=head2 Two-face referencesSuppose you want to create an object which is accessible as both anarray reference and a hash reference, similar to theL<pseudo-hash|perlref/"Pseudo-hashes: Using an array as a hash">builtin Perl type.  Let's make it better than a pseudo-hash byallowing index 0 to be treated as a normal element.  package two_refs;  use overload '%{}' => \&gethash, '@{}' => sub { $ {shift()} };  sub new {    my $p = shift;    bless \ [@_], $p;  }  sub gethash {    my %h;    my $self = shift;    tie %h, ref $self, $self;    \%h;  }  sub TIEHASH { my $p = shift; bless \ shift, $p }  my %fields;  my $i = 0;  $fields{$_} = $i++ foreach qw{zero one two three};  sub STORE {    my $self = ${shift()};    my $key = $fields{shift()};    defined $key or die "Out of band access";    $$self->[$key] = shift;  }  sub FETCH {    my $self = ${shift()};    my $key = $fields{shift()};    defined $key or die "Out of band access";    $$self->[$key];  }Now one can access an object using both the array and hash syntax:

⌨️ 快捷键说明

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