📄 overload.3
字号:
to overload constant pieces of regular expressions..PPThe corresponding values are references to functions which take three arguments:the first one is the \fIinitial\fR 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 \f(CW\*(C`q\*(C'\fR\- and \f(CW\*(C`qr\*(C'\fR\- constants, it is \f(CW\*(C`q\*(C'\fR in single-quotecontext (comes from strings, regular expressions, and single-quote \s-1HERE\s0documents), it is \f(CW\*(C`tr\*(C'\fR for arguments of \f(CW\*(C`tr\*(C'\fR/\f(CW\*(C`y\*(C'\fR operators,it is \f(CW\*(C`s\*(C'\fR for right-hand side of \f(CW\*(C`s\*(C'\fR\-operator, and it is \f(CW\*(C`qq\*(C'\fR otherwise..PPSince an expression \f(CW"ab$cd,,"\fR is just a shortcut for \f(CW\*(Aqab\*(Aq . $cd . \*(Aq,,\*(Aq\fR,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..PPNote that it is probably meaningless to call the functions \fIoverload::constant()\fRand \fIoverload::remove_constant()\fR from anywhere but \fIimport()\fR and \fIunimport()\fR methods.From these methods they may be called as.PP.Vb 6\& sub import {\& shift;\& return unless @_;\& die "unknown import: @_" unless @_ == 1 and $_[0] eq \*(Aq:constant\*(Aq;\& overload::constant integer => sub {Math::BigInt\->new(shift)};\& }.Ve.SH "IMPLEMENTATION".IX Header "IMPLEMENTATION"What follows is subject to change \s-1RSN\s0..PPThe table of methods for all operations is cached in magic for thesymbol table hash for the package. The cache is invalidated duringprocessing of \f(CW\*(C`use overload\*(C'\fR, \f(CW\*(C`no overload\*(C'\fR, new functiondefinitions, and changes in \f(CW@ISA\fR. However, this invalidation remainsunprocessed until the next \f(CW\*(C`bless\*(C'\fRing into the package. Hence if youwant to change overloading structure dynamically, you'll need anadditional (fake) \f(CW\*(C`bless\*(C'\fRing to update the table..PP(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 \f(CW%ENV\fR magic and their taintmagic. However, the magic which implements overloading is applied tothe stashes, which are rarely used directly, thus should not slow downPerl.).PPIf 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..PPIn fact, if \f(CW\*(C`use overload\*(C'\fR 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 \f(CW\*(C`use overload\*(C'\fR and without it. So farthere have been no reports of substantial speed degradation if Perl iscompiled with optimization turned on..PPThere is no size penalty for data if overload is not used. The onlysize penalty if overload is used in some package is that \fIall\fR thepackages acquire a magic during the next \f(CW\*(C`bless\*(C'\fRing into thepackage. This magic is three-words-long for packages withoutoverloading, and carries the cache table if the package is overloaded..PPCopying (\f(CW\*(C`$a=$b\*(C'\fR) is shallow; however, a one-level-deep copying iscarried out before any operation that can imply an assignment to theobject \f(CW$a\fR (or \f(CW$b\fR) refers to, like \f(CW\*(C`$a++\*(C'\fR. You can override thisbehavior by defining your own copy constructor (see \*(L"Copy Constructor\*(R")..PPIt is expected that arguments to methods that are not explicitly supposedto be changed are constant (but this is not enforced)..SH "Metaphor clash".IX Header "Metaphor clash"One may wonder why the semantic of overloaded \f(CW\*(C`=\*(C'\fR is so counter intuitive.If it \fIlooks\fR counter intuitive to you, you are subject to a metaphorclash..PPHere is a Perl object metaphor:.PP\&\fI object is a reference to blessed data\fR.PPand an arithmetic metaphor:.PP\&\fI object is a thing by itself\fR..PPThe \fImain\fR problem of overloading \f(CW\*(C`=\*(C'\fR is the fact that these metaphorsimply different actions on the assignment \f(CW\*(C`$a = $b\*(C'\fR if \f(CW$a\fR and \f(CW$b\fR areobjects. Perl-think implies that \f(CW$a\fR becomes a reference to whatever\&\f(CW$b\fR was referencing. Arithmetic-think implies that the value of \*(L"object\*(R"\&\f(CW$a\fR is changed to become the value of the object \f(CW$b\fR, preserving the factthat \f(CW$a\fR and \f(CW$b\fR are separate entities..PPThe difference is not relevant in the absence of mutators. Aftera Perl-way assignment an operation which mutates the data referenced by \f(CW$a\fRwould change the data referenced by \f(CW$b\fR too. Effectively, after\&\f(CW\*(C`$a = $b\*(C'\fR values of \f(CW$a\fR and \f(CW$b\fR become \fIindistinguishable\fR..PPOn 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 possible to freely mix two contradictingmetaphors, overloading allows the arithmetic way to write things \fIasfar as all the mutators are called via overloaded access only\fR. Theway it is done is described in \*(L"Copy Constructor\*(R"..PPIf some mutator methods are directly applied to the overloaded values,one may need to \fIexplicitly unlink\fR other values which references thesame value:.PP.Vb 6\& $a = new Data 23;\& ...\& $b = $a; # $b is "linked" to $a\& ...\& $a = $a\->clone; # Unlink $b from $a\& $a\->increment_by(4);.Ve.PPNote that overloaded access makes this transparent:.PP.Vb 3\& $a = new Data 23;\& $b = $a; # $b is "linked" to $a\& $a += 4; # would unlink $b automagically.Ve.PPHowever, it would not make.PP.Vb 2\& $a = new Data 23;\& $a = 4; # Now $a is a plain 4, not \*(AqData\*(Aq.Ve.PPpreserve \*(L"objectness\*(R" of \f(CW$a\fR. But Perl \fIhas\fR a way to make assignmentsto an object do whatever you want. It is just not the overload, but\&\fItie()\fRing interface (see \*(L"tie\*(R" in perlfunc). Adding a \s-1\fIFETCH\s0()\fR methodwhich returns the object itself, and \s-1\fISTORE\s0()\fR method which changes thevalue of the object, one can reproduce the arithmetic metaphor in itscompleteness, at least for variables which were \fItie()\fRd from the start..PP(Note that a workaround for a bug may be needed, see \*(L"\s-1BUGS\s0\*(R".).SH "Cookbook".IX Header "Cookbook"Please add examples to what follows!.Sh "Two-face scalars".IX Subsection "Two-face scalars"Put this in \fItwo_face.pm\fR in your Perl library directory:.PP.Vb 6\& package two_face; # Scalars with separate string and\& # numeric values.\& sub new { my $p = shift; bless [@_], $p }\& use overload \*(Aq""\*(Aq => \e&str, \*(Aq0+\*(Aq => \e&num, fallback => 1;\& sub num {shift\->[1]}\& sub str {shift\->[0]}.Ve.PPUse it as follows:.PP.Vb 4\& require two_face;\& my $seven = new two_face ("vii", 7);\& printf "seven=$seven, seven=%d, eight=%d\en", $seven, $seven+1;\& print "seven contains \`i\*(Aq\en" if $seven =~ /i/;.Ve.PP(The second line creates a scalar which has both a string value, and anumeric value.) This prints:.PP.Vb 2\& seven=vii, seven=7, eight=8\& seven contains \`i\*(Aq.Ve.Sh "Two-face references".IX Subsection "Two-face references"Suppose you want to create an object which is accessible as both anarray reference and a hash reference..PP.Vb 12\& package two_refs;\& use overload \*(Aq%{}\*(Aq => \e&gethash, \*(Aq@{}\*(Aq => sub { $ {shift()} };\& sub new {\& my $p = shift;\& bless \e [@_], $p;\& }\& sub gethash {\& my %h;\& my $self = shift;\& tie %h, ref $self, $self;\& \e%h;\& }\&\& sub TIEHASH { my $p = shift; bless \e 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];\& }.Ve.PPNow one can access an object using both the array and hash syntax:.PP.Vb 3\& my $bar = new two_refs 3,4,5,6;\& $bar\->[2] = 11;\& $bar\->{two} == 11 or die \*(Aqbad hash fetch\*(Aq;.Ve.PPNote several important features of this example. First of all, the\&\fIactual\fR type of \f(CW$bar\fR is a scalar reference, and we do not overloadthe scalar dereference. Thus we can get the \fIactual\fR non-overloadedcontents of \f(CW$bar\fR by just using \f(CW$$bar\fR (what we do in functions whichoverload dereference). Similarly, the object returned by the\&\s-1\fITIEHASH\s0()\fR method is a scalar reference..PPSecond, we create a new tied hash each time the hash syntax is used.This allows us not to worry about a possibility of a reference loop,which would lead to a memory leak..PPBoth these problems can be cured. Say, if we want to overload hashdereference on a reference to an object which is \fIimplemented\fR as ahash itself, the only problem one has to circumvent is how to accessthis \fIactual\fR hash (as opposed to the \fIvirtual\fR hash exhibited by theoverloaded dereference operator). Here is one possible fetching routine:.PP.Vb 8\& sub access_hash {\& my ($self, $key) = (shift, shift);\& my $class = ref $self;\& bless $self, \*(Aqoverload::dummy\*(Aq; # Disable overloading of %{}\& my $out = $self\->{$key};\& bless $self, $class; # Restore overloading\& $out;\& }.Ve.PPTo remove creation of the tied hash on each access, one may an extralevel of indirection which allows a non-circular structure of references:.PP.Vb 10\& package two_refs1;\& use overload \*(Aq%{}\*(Aq => sub { ${shift()}\->[1] },\& \*(Aq@{}\*(Aq => sub { ${shift()}\->[0] };\& sub new {\& my $p = shift;\& my $a = [@_];\& my %h;\& tie %h, $p, $a;\& bless \e [$a, \e%h], $p;\& }\& sub gethash {\& my %h;\& my $self = shift;\& tie %h, ref $self, $self;\& \e%h;\& }\&\& sub TIEHASH { my $p = shift; bless \e shift, $p }\& my %fields;\& my $i = 0;\& $fields{$_} = $i++ foreach qw{zero one two three};\& sub STORE {\& my $a = ${shift()};\& my $key = $fields{shift()};\& defined $key or die "Out of band access";\& $a\->[$key] = shift;\& }\& sub FETCH {\& my $a = ${shift()};\& my $key = $fields{shift()};\& defined $key or die "Out of band access";\& $a\->[$key];\& }.Ve.PPNow if \f(CW$baz\fR is overloaded like this, then \f(CW$baz\fR is a reference to areference to the intermediate array, which keeps a reference to anactual array, and the access hash. The \fItie()\fRing object for the accesshash is a reference to a reference to the actual array, so.IP "\(bu" 4There are no loops of references..IP "\(bu" 4Both \*(L"objects\*(R" which are blessed into the class \f(CW\*(C`two_refs1\*(C'\fR arereferences to a reference to an array, thus references to a \fIscalar\fR.Thus the accessor expression \f(CW\*(C`$$foo\->[$ind]\*(C'\fR involves nooverloaded operations..Sh "Symbolic calculator".IX Subsection "Symbolic calculator"Put this in \fIsymbolic.pm\fR in your Perl library directory:.PP.Vb 2\& package symbolic; # Primitive symbolic calculator\& use overload nomethod => \e&wrap;\&\& sub new { shift; bless [\*(Aqn\*(Aq, @_] }\& sub wrap {\& my ($obj, $other, $inv, $meth) = @_;\& ($obj, $other) = ($other, $obj) if $inv;\& bless [$meth, $obj, $other];\& }.Ve.PPThis module is very unusual as overloaded modules go: it does notprovide any usual overloaded operators, instead it provides the LastResort operator \f(CW\*(C`nomethod\*(C'\fR. In this example the correspondingsubroutine returns an object which encapsulates operations done overthe objects: \f(CW\*(C`new symbolic 3\*(C'\fR contains \f(CW\*(C`[\*(Aqn\*(Aq, 3]\*(C'\fR, \f(CW\*(C`2 + newsymbolic 3\*(C'\fR contains \f(CW\*(C`[\*(Aq+\*(Aq, 2, [\*(Aqn\*(Aq, 3]]\*(C'\fR..PPHere is an example of the script which \*(L"calculates\*(R" the side ofcircumscribed octagon using the above package:.PP.Vb 4\& require symbolic;\& my $iter = 1; # 2**($iter+2) = 8\& my $side = new symbolic 1;\& my $cnt = $iter;\&\& while ($cnt\-\-) {\& $side = (sqrt(1 + $side**2) \- 1)/$side;\& }\& print "OK\en";.Ve.PPThe value of \f(CW$side\fR is.PP.Vb 2\& [\*(Aq/\*(Aq, [\*(Aq\-\*(Aq, [\*(Aqsqrt\*(Aq, [\*(Aq+\*(Aq, 1, [\*(Aq**\*(Aq, [\*(Aqn\*(Aq, 1], 2]],\& undef], 1], [\*(Aqn\*(Aq, 1]].Ve.PPNote that while we obtained this value using a nice little script,there is no simple way to \fIuse\fR this value. In fact this value maybe inspected in debugger (see perldebug), but only if\&\f(CW\*(C`bareStringify\*(C'\fR \fBO\fRption is set, and not via \f(CW\*(C`p\*(C'\fR command..PPIf one attempts to print this value, then the overloaded operator\&\f(CW""\fR will be called, which will call \f(CW\*(C`nomethod\*(C'\fR operator. Theresult of this operator will be stringified again, but this result isagain of type \f(CW\*(C`symbolic\*(C'\fR, which will lead to an infinite loop..PPAdd a pretty-printer method to the module \fIsymbolic.pm\fR:.PP.Vb 8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -