This file was automatically generated from http://svn.pugscode.org/pugs/docs/Perl6/Spec/de_Overload.pod on Wed Nov 7 11:22:59 2007 GMT, revision 18807.
Synopsis 13: Ãberladen
Larry Wall <larry@wall.org>
Moritz Lenz <moritz@faui2k3.org>
Maintainer: Larry Wall <larry@wall.org> Datum: 2. November 2004 Letzte Ãnderung: : 21. September 2007 Nummer: 13 Version: 10
Diese Synopsis diskutiert die Teile von Apokalypse 12, die eigentlich Apokalypse 13 hätten sein sollen.
Der Ãberladungsmechanismus von Perl 5 wird in Perl 6 durch Multimethoden
abgelöst. Fast alle internen Funktionen sind als multi-Funktionen oder
-Methoden mit allgemeinen Typen definiert.
Eingebaute Operatoren sind lediglich komisch benannte Funktionen, die einer
alternativen Aufrufsyntax folgen. Um sie zu überladen muss man nur eigene
multi-Funktionen und Methoden definieren, die mit spezifischeren Typen
arbeiten.
Bei unären Operatoren macht das effektiv wenig Unterschied, aber bei binären Operatoren behebt das Perl 5s Problem, dass nur der Typ des linken Arguments beachtet wird. Da beide Argumente benutzt werden um zu entscheiden, welche Funktion aufgerufen wird, benötigt man keine Tricks mehr, die die Argumente vertauschen um dem Typ des rechten Arguments Beachtung zu schenken. Und man benötigt kein spezielles Flag mehr um zu erfahren, ob die Argumente vertauscht wurden.
Für mehr Informationen über Multimethoden siehe S12.
Es gibt keine spezielle use overload-Syntax mehr, auÃer normalen
multi-Methoden. Um ein normales builtin zu überladen, kann man so etwas
benutzen:
multi sub *uc (TurkishStr $s) {...}
Wenn man nun uc auf einen türkischen String aufruft, wird die gerade
definierte Funktion anstelle der eingebauten aufgerufen. Durch das Platzieren
der multi in den *-Namensraum lassen es in jedem Paket auftauchen, aber
so lange niemand anderes eine Version von uc auf TurkishStr gibt es
keine Kollisionen.
Die Typen der Parameter sind Bestandteil des longname jeder
multi-Funktion oder Methode. Wenn man also Stringkonkatenation for
Arabische Strings überladen will, um verschiedene Ligaturen zu behandeln, geht
das so:
multi sub *infix:<~>(ArabicStr $s1, ArabicStr $s2) {...}
multi sub *infix:<~>(Str $s1, ArabicStr $s2) {...}
multi sub *infix:<~>(ArabicStr $s1, Str $s2) {...}
Die use overload-Syntax hatte einen Vorteil über Perl 6s Syntax: es war
leicht, mehrere Operatoren mit der selben Operation zu überladen.
Das kann man in Perl 6 mit Aliasing erreichen:
multi sub unimpl (MyFoo $x, MyFoo $y) { upchuck(); }
&infix:<+> ::= &unimpl;
&infix:<-> ::= &unimpl;
&infix:<*> ::= &unimpl;
&infix:</> ::= &unimpl;
Das ist eine Möglichkeit, aber häufig haben alle Alternativen den selben Namen, und variieren in ihrer Signatur. Einige Operatoren sind kommutativ, oder können in einer anderen Form ihre Argumente in unterschiedlichen Reihenfolgen akzeptieren. Perl erlaubt die Deklaration mehrerer Signaturen für einen Funktionsrumpf, und sie werden so interpretiert als wären es mehrere Multimethoden. Wenn man schreibt
multi sub infix:<+> (Us $us, Them $them) |
(Them $them, Us $us) { myadd($us,$them) }
ist das gleichbedeutend mit
multi sub infix:<+> (Us $us, Them $them) { myadd($us,$them) }
multi sub infix:<+> (Them $them, Us $us) { myadd($us,$them) }
auÃer dass es wirklich nur einen Funktionsrumpf gibt. Wenn man eine
state-Variable in dem Funktionsrumpf deklariert, gibt es nur eine davon.
Man beachte das Fehlen von * auf bei den obigen Definitionen. Das
bedeutet, dass diese Definition der Addition syntaktisch nur in dem
Scope gilt, in dem das infix:<+> definiert oder importiert ist.
Ãhnliche Beschränkungen gelten für lexikalisch gescopte Subroutinen
und Multimethoden. Meistens will man die Multimethoden in den *
Namensraum, damit sie überall funktionieren.
When you use the multiple signature syntax, the alternate signatures must all bind the same set of formal variable names, though they are allowed to vary in any other way, such as by type, or by which parameters are considered optional or named-only or slurpy. In other words, the compiler is allowed to complain if any of the alternatives omits any of the variable names. This is intended primarily to catch editing errors.
Conjectural: If the first parameter to a multi signature is followed by an invocant colon, that signature represents two signatures, one for an ordinary method definition, and one for the corresponding multi definition that has a comma instead of the colon. This form is legal only where the standard method definition would be legal, and only if any declared type of the first parameter is consistent with $?CLASS.
Dispatch is based on a routine's signature declaration without regard
to whether the routine is defined yet. If an attempt is made to
dispatch to a declared but undefined routine, Perl will redispatch
to an AUTODEF submethod [conjectural] as appropriate to define the routine. This provides
a run-time mechanism for fallbacks. By default, these declarations
are taken at face value and do not specify any underlying semantics.
As such, they're a "shallow" interpretation.
However, sometimes you want to specify a "deep" interpretation of your operators. That is, you're specifying the abstract operation, which may be used by various shallow operators. Any deep multi declarations will be "amplified" into all the shallow operators that can be logically based on it. If you say:
multi sub infix:<%> (Us $us, Them $them) is deep { mymod($us,$them) }
then
multi sub infix:<%=> (Us $us, Them $them) { $us = $us % $them }
is also generated for you (unless you define it yourself).
The mappings of magical names to sub definitions is controlled by the
%?DEEPMAGIC compiler hash. Pragmas can influence the contents of
this hash over a lexical scope, so you could have different policies
on magical autogeneration. The default mappings correspond to the
standard fallback mappings of Perl 5 overloading.
These deep mappings are mainly intended for infix operators that would have difficulty naming all their variants. Prefix operators tend to be simpler; note in particular that
multi prefix:<~> is deep {...}
is better written:
method Str {...}
(see below).
A class may define methods that allow it to respond as if it were a routine, array, or hash. The long forms are as follows:
method postcircumfix:<( )> (|$capture) {...}
method postcircumfix:<[ ]> (*@@slice) {...}
method postcircumfix:<{ }> (*@@slice) {...}
Those are a bit unwieldy, so you may also use these short forms:
method &.( |$capture ) {...}
method @.[ *@@slice ] {...}
method %.{ *@@slice } {...}
The sigil-dot sequence in these short forms autogenerates the corresponding public operators, in exactly the same way that the sigil-dot in:
has $.action;
has @.sequence;
has %.mapping;
autogenerates public accessor methods.
And because it uses the same method-autogeneration mechanism, the specific sigil used to specify a short-form postcircumfix operator doesn't actually matter...as long as it's followed by a dot and the bracket pair containing the signature. (Though it's probably kinder to future readers of your code to stick with the "natural" sigil for each type of bracket.)
Note that the angle bracket subscripting form .<a b c>
automatically translates itself into a call to .{'a','b','c'} ,
so defining methods for angles is basically useless.
The expected semantics of &.() is that of a type coercion which may
or may not create a new object. So if you say:
$fido = Dog.new($spot)
it certainly creates a new Dog object. But if you say:
$fido = Dog($spot)
it might call Dog.new, or it might pull a Dog with Spot's
identity from the dog cache, or it might do absolutely nothing if
$spot already knows how to be a Dog. As a fallback, if no
method responds to a coercion request, the class will be asked to attempt to
do Dog.new($spot) instead.
It is also possible (and often preferable) to specify coercions from the other end, that is, for a class to specify how to coerce one of its values to some other class. If you define a method whose name is a declared type, it is taken as a coercion to that type:
method Str { self.makestringval() }
As with all methods, you can also export the corresponding multi:
method Str is export { self.makestringval() }
in which case you can use both calling forms:
$x.Str
Str($x)
If the source class and the destination class both specify a coercion routine, the ambiguity is settled by the ordinary rules of multiple dispatch. Usually the source class will have the more specific argument and will win; ties are also possible, and those calls will fail. Additional arguments may sway the dispatch one way or the other depending on the candidate list.
Note that, because the name of an anonymous class is unknown, coercion to an anonymous class can only be specified by the destination class:
$someclass = generate_class();
$someclass($x);