Übersicht ||
0:Vor |
1:Ge |
2:Theo |
3: Variablen |
4: Operatoren |
5: Ein- und Ausgabe |
6:{} |
7:Sub |
8:OOP |
9:Rx ||
A:Index |
B:Tab |
C:Tour |
D:Delta |
E:Links
1st law of language redesign: Everyone wants the colon for their particular syntax. 2nd law of language redesign: Larry gets the colon for whatever he wants.
Logik im Skalarkontext
smartmatch Operator
Perl 6 hat sehr viele Operatoren und etliche davon sind neu oder haben eine veränderte Bedeutung. Das macht die Sprache noch ausdrucksstärker, effektiver und genauer. Der unangefochtene König all dieser Operatoren ist jedoch '~~', der Smartmatchoperator, dem universalen 'vergleich das !'-Operator. Er vergleicht Zahlen, Strings (kann also
== und eq ersetzen), aber auch Wertebereiche, Junctions, Arrays, Hashes, Ergebnisse von Subroutinen, und kann fast alles abfragen was die Symboltabelle an Informationen bietet, wie: "Kennt dieses Module eine Routine mit dem Namen oder der Signatur?", oder "Hat dieses Objekt grad so eine Methode oder kennt sie so eine role?" und vieles mehr. Er wird natürlich auch für Perl's Spezialdisziplin verwendet: den regulären Ausdrücken, die jetzt nach vollständiger Überarbeitung
rules heissen. Dafür eignet er sich auch besser als das alte '=~', da es ja keine Zuweisung ist, daher kein Gleichheitszeichen enthalten sollte. '~' ist korrekt, da es jetzt Stringkontext anzeigt und Suchen ist die häufigste Stringoperation. Den Syntax der
rules lest ihr bitte auf der
9. Tafel nach, denn sie sind eine Sprache in der Sprache und würden den Rahmen dieses Kapitel überdehnen. Aber da
Regex für Perl sind, was der Stabhochsprung für Sergej Bubka, fangen wie in den Beispielen damit an:
"Sergej Bubka." ~~ /ej/; # positiv da enthalten
"Sergej Bubka."!~~ /buba/; # positiv da nicht enthalten
"Sergej Bubka." ~~ s/ej/ejevitsch/; # "Sergejevitsch Bubka"
"Sergej Bubka." ~~ s:g/e/u/; # "Surguj Bubka", Optionen kommen an den Anfang
7 ~~ 7; # wahr denn 7 == 7
7 ~~ '7'; # wahr kennt man ja alles aus perl5
7 ~~ 5 .. 8; # wahr, .. produziert Bereichsobjekt im Skalarkontext
7 ~~ 5 .. 7; # wahr, denn die zahl ist in dem bereich
7 ~~ 5 .. *; # wahr, Bereich geht bis Unendlich
7 ~~ 5 .. Inf; # wahr, andere Schreibweise
7 ~~ 7 .. 5; # unwahr, leerer Bereich
$wahr = 1.5 ~~ 1^..^2; # wahr,
$wahr = 2 ~~ 1^..^2; # nicht wahr, Schranke ist ausgeschlossen
eine Variable anwenden kann aber auch Zahlen, Arrays oder Signaturen verleichen kann und sogar Zugehörigkeit von Methoden zu Klassen prüfen kann oder auch Auskunft geben kann ob ein Objekt jene Role vollführen kann oder dieser Hashkey existiert.
vergleichende Operatoren
Der Name sagt es schon: sie vergleichen 2 Werte und liefern dabei meist das Ergebnis 1 oder 0 (leer) zurück. Dabei ähneln sie ein wenig den
kontexterzeugende Skalaroperatoren weil manche von ihnen die Werte als Text ansehen und manche versuchen sie als Zahl interpretieren und dann diese Zahlen vergleichen. Welche von beiden Arbeitsweisen sie verfolgen sieht man meist am Namen selbst, da Vergleichoperatoren die aus Buchstaben bestehen Text vergleichen und Vergleichsoperatoren aus mathematischen Symbolen arithmetisch Vergleichen. Dies sollte aber alles bekannt sein, weil es hier kaum Änderungen zu Perl5 gibt.
| numerisch | text | Bedeutung |
= | eq | gleich |
| ! | ne | ungleich |
| < | lt | kleiner als |
| <= | le | kleiner gleich |
| > | gt | größer als |
| >= | ge | größer gleich |
| <=> | leg | Vergleich |
$ergebnis = 1.0 == 0b01; # 1, beides numerisch gleich
$ergebnis = 'jo'== 'mei'; # 1, beides 0
$ergebnis = 1.0 eq 1; # 0, ungleicher Text
$ergebnis = 1 eq 1; # 1, gleicher Text
$ergebnis = 'jo'ne 'mei'; # 1, ungleicher Text, entspricht !eq
$ergebnis = 4 > 5 ; # 0, da 4 weniger 5 ist
$ergebnis = 5 >= 5 ; # 1, da gleich
$ergebnis = 'a' lt 'b'; # 1, a ist im Alphabet weiter vorne, also "kleiner"
$ergebnis = '4' lt '5'; # 1, 4 hat kleineren Wert in der ASCII-Tabelle
Etwas mehr Abwechlung liefern die Operatoren in der letzten Zeile der Tabelle, da sie -1 (im Falle links ist kleiner) 0 (beide gleich) oder 1 (links ist größer). Dabei wandeln
<=> und
leg wie schon gezeigt in numerischen oder string Kontext. Möchte man dies nicht, so sollte man
cmp verwenden, was überdies den Vorteil bietet, das Perl 6 standartmässig über eine interne
Order -Klasse verfügt. Die Werte -1, 0 und 1 sind auch in Wirklichkeit Umwandlungen der Werte
Order::Increase,
Order::Same und
Order::Decrease in den numerischen Kontext. Module wie DateTime können Methoden liefern wie Uhrzeit und Datum verglichen werden können und auf diese kann der
cmp -Operator angewendet werden. Falls es aber unbedingt ein boolsches Ergebnis sein muß gibt es jetzt auch die neuen Operatoren
before und
after.
2 <=> 3 # -1, entspricht +2 cmp +3
'B' leg 'B' # 0, entspricht ~'B' cmp ~'B'
5 before 8 # wahr
7 after 9 # das natürlich nicht
Neu sind auch die Vergleichoperatoren
=== und
eqv. Ersterer prüft die sogenannte "Identität", also Typ und Inhalt der Variable.
eqv fast das selbe, geht aber mehr auf, nach derzeitigem Stand, dynamische Eigenschaften von Objekten ein.
[1,2] === [1,2] # unwahr, da verschiedene Arrays
@a === @a # wahr
Darüber hinaus gibt es noch "=:=". Es prüft ob 2 Variablen aneinander
gebunden sind. Zu fast jedem Operator hier (ausser
before und
after) gibt es auch noch eine negierte Form die aus einem vorgestellten
! resultiert. Auch wenn es schon sehr schräg ist statt
>,
!<= zu benutzen ist in Perl 6 die Grenze bei
! erreicht, da ein
!! bereits zum
ternären Operator gehört.
Verkettungen
Eine der nützlichsten Neuerungen ist, daß alle vergleichende Operatoren mit 2 Operanden jetzt verkettbar (chainable) sind und auch alle Vergleiche mit "==" verkettbar sind.
13 < $alter < 17 # o jeh die Pubertät
13 < $alter == $alter < 17 # fast das selbe, $alter wird hier 2mal evaluiert
Junctions
Stell ich jetzt schon vor, weil sie nur Kurzschreibweisen für Mehrfachverknüpfungen der oben vorgestellten Operationen (and, or und xor) sind. Um Junctions zu formulieren verwendet man die ehemalig bitverändernden Operatoren "&,|,^" und runde Klammern. Die Schlüsselworte "all, any, one und none" helfen den Einsatz der Junction bei Abfragen lesbar zu halten.
| Funktion | Operator | Verknüpfung | wahr wenn ... |
| all | & | and | alle Bedingungen erfüllt |
| any | | | or | mindestens eine erfüllt ist |
| one | ^ | xor | genau eine erfüllt ist |
| none | | not | alle unzutreffend |
(1|2|3) + 4; # 5|6|7
(1|2) + (3&4); # (4|5) & (5|6)
2 == (2|3|5|7); # ist wahr
(2|8) == (2|3|5|7); # auch wahr
(2&8) == (2|3|5|7); # nicht wahr
all(2,8) == any(2,3,5,7); # andere Schreibweise
all(@a) == any(@b); # andere Schreibweise
logische Operatoren
Logische Auswahloperatoren prüfen Skalare ob sie leer sind und geben je nach Lage den Inhalt einer der beiden mit ihnen verknüpften Variablen. Sie werden in Perl5 vor allem wegen ihrer Fähigkeit benutzt, daß sie die Berechnung vorzeitig abbrechen, wenn das Ergebnis schon fest steht, weswegen sie auch Kurzschlussoperatoren genannt werden. Ihr Verhalten richtet sich nach den grundlegenden logischen Verknüpfungen, was man auch zur Ablaufkontrolle nutzen kann
siehe Kapitel 6:
| Operator | NP Variante | Bedeutung | Kurzschluss | | && | and | logisches UND | ja | | || | or | logisches ODER | ja | | // | (orelse) | prüft Definiertheit | ja | | ^^ | xor | exklusives ODER | nein | | ! | not | logisches NOT | nein | |
| | | and | or | xor | | 0 | 0 | 0 | 0 | 0 | | 0 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 1 | 1 | | 1 | 1 | 1 | 1 | 0 | |
$eis = ($schoko && $vanille); # beide Schreibweisen sind gleichwertig
$eis = $schoko && $vanille; # Klammern gruppieren ja nur
$eis = $schoko || $vanille; #
In diesem Beispiel bricht der Operator ab, und gibt Inhalt von $schoko zurück, wenn $schoko leer ist('' oder 0), weil in dem Fall das Ergebnis nie mehr positiv werden kann(siehe Tabelle). Ist $schoko nicht leer wird der Inhalt von $vanille an $eis überwiesen.
Das || funktioniert andersherum und würde den Wert aus $vanille überweisen wenn $schoko leer wäre. u.s.w. NP in der Tabelle meint "niedrige Priorität", da in kombinierten Ausdrücken das zum verbinden von Werten gedachte || wesentlich eher ausgewertet wird als ein
or, daß mehr zum Verknüpfen von Ausdrücken gedacht ist, die man dann nicht umklammern braucht, weil die NP-Varianten zum gleichen Ergebnis führen, als würde man die Teilausdrücke mit Klammern umgeben und zwischen den Klammern die Alternativen mit hoher Prioritätverwenden.
Einzig neu an diesen 4 Operatorpaaren ist der
err (Variante mit hoher Priorität) oder
// Operator (eingeführt in 5.10), der dem or ähnelt, jedoch nicht auf Inhalt sondern Definiertheit des ersten Skalars achtet. Das ermöglicht folgendes abzukürzen:
$breite = defined $sonderbreite ? $sonderbreite : $standardbreite; # Perl5
$breite = $sonderbreite // $standartbreite; # Perl6 Äquivalent
Die Operatoren
^^, xor,
! und
not funktioniert wieder genau wie in Perl5. Doch ist xor kein echter Kurzschlussoperator, da er in jedem Fall beide Variablen prüft. Auch
not nicht da es sich nur einen Operanden bezieht.
Besondere Varianten von
or und
and sind sind die vollständig neuen
orelse und
andthen. Sie übertragen Spezialvariablen aus dem Geltungsbereich der linken Seite in den rechten, soweit es die Ergebnisse gebieten. Mit
andthen kann man mit Kontextvariable im Falle eines Positiven Ergebnisses weiterrechnen,
orelse bietet sich an, wenn mann im Falle eines Fehlers die Fehlermeldung getrennt auswerten will.
test1() andthen test2() entspricht: test1() andthen -> $_ { test2() }
test1() orelse test2() entspricht: test1() orelse -> $! { test2() }
ternärer Operator
Der im letzten Absatz verwendete ternären Operator ($a ? $b : $c - auch Bedingunsoperator genannt) ist eine aus C übernommene Kurzschreibweise für "if ($a) {$b} else {$c}", wobei anstatt jeder Variable natürlich auch ein Ausdruck stehen kann. Dieser Operator wurde umbenannt da
? und
: bereits andere Aufgaben haben und die neue Schreibweise ($a ?? $b !! $c) konsistenter zu den funktionsähnlichen, eben beschriebenen Auswahloperatoren passt, die ebenfalls immer aus 2 gleichen Zeichen bestehen. Auch die Verwendung des Ausrufungszeichen ist konsistenter zum restlichen Perl 6 wo es immer etwas verneinendes oder gegenteiliges (private methoden als gegenteil von öffentlichen methoden) anzeigt.
print "Und die Antwort ist: ", $wirklich ? "Ja" : "Nein"; # Perl 5
print "Und die Antwort ist: ", $wirklich ?? "Ja" !! "Nein"; # Perl 6, entspricht:
print "Und die Antwort ist: ", do { if $wirklich {"Ja"} else {"Nein"} };
Flipflop
Eine besonderer logischer Operator ist der flipflop. Man schrieb ihn früher
.. (im Skalarkontext), jetzt aber zur besseren Unterscheidung ff(awk-stil) oder fff(sed-stil). Links und rechts von ihm wird jeweils ein Wert angegeben, diese sind dann die Anfangs,- und Endwerte eines gesuchten Bereiches. Der flipflop operator wird meist innerhalb einer Schleife verwendet. Sobald der linke Wert einen positiven Vergleich ergibt, liefert auch der gesamte Ausdruck ein 'true' zurück, solange bis der rechte Wert zutrifft. Wobei die awk-Variante nach dem Erfolg des linken Wertes gleich auch noch den rechten prüft. Die sed-Variante tut dies erst im nächsten Durchlauf.
# gibt aus: anfang war das ende
say if /anfang/ ff /ende/ for <am anfang war das ende noch nicht abzusehen>;
# gibt aus: anfangende
say if /anfang/ ff /ende/ for <am anfangende war das ende noch nicht abzusehen>;
# gibt aus: anfangende war das ende
say if /anfang/ fff /ende/ for <am anfang war das ende noch nicht abzusehen>;
# gibt ab "anfang" alles aus (* bedeutet Inf)
say if /anfang/ ff * for <am anfang war das ende noch nicht abzusehen>;
Dateitestoperatoren
Diese berichten über Eigenschaften von Dateien und Verzeichnissen und sind deshalb im
Kapitel 5 zu finden, wo es um Ein- und Ausgabe geht.
yadda Operatoren
Mit Yadda Operatoren werden leere Subroutinen gekennzeichnet. Näheres dazu im
Kapitel7.
kontexterzeugende Skalaroperatoren
Auch wenn es beim Zuweisen praktisch ist, daß fast alles in Skalare passt, können Operatoren damit Probleme bekommen, da manche nur sinnvoll auf ganze Zahlen angewendet werden können, andere nur auf Text ... Deswegen wandeln die folgenden Operatoren zuerst den Inhalt der Skalare in den benötigten Kontext, bevor der Operator selber angewand wird. Den jeweiligen Kontext erkennt man am ersten Buchstaben der meisst 2 Zeichen langen Operatoren. Diese Vorzeichen können auch allein verwendet werden um Skalare in den entsprechenden Kontext zu wandeln.
boolscher Kontext
Im boolschen Kontext kann das Ergebnis nur ja (1) oder nein (leer) sein wie bei einer einfachen Frage. Deswegen erkennt man jetzt am Fragezeichen diesen Kontext, der Rest ist wie bei den logischen Operatoren nur das die ganzen Variableninhalte erst in 0 und 1 umgewandelt werden und dann wird berechnet. Nehmen wir an das $saddam eine '5-' bekommen hat und $george eine 0.0 ist ...
$wahr = ?$saddam; # macht 1
$wahr = true $saddam; # dito, Schreibweise mit höherer Priorität
$wahr = ! $saddam; # macht 0
$wahr = not$saddam; # dito, Schreibweise mit höherer Priorität
$wahr = $saddam ?& $george; # nö
$wahr = $saddam ?| $george; # wahr
$wahr = $saddam ?^ $george; # klaro
Aber auch die meisten
Vergleichsoperatoren geben als Ergebnisse auch nur '' oder 1 und erzeugen damit einen boolschen Kontext.
numerischer Kontext
Bedeutet das man den Inhalt der Skalare nur als Zahl sieht und alles "unverständlichen" Buchstaben weglässt, so daß aus auch aus "mächtig" der Wert 0 wird. Der numerische Kontext umfasst Zahlen mit oder ohne Nachkommastellen und kann mit Zahlen in binärer, okal, dezimal oder hexadezimaler Schreibweise umgehen. Dies bedeutet das 1, 1.0 und 0b01 im numerischen Kontext gleich sind.
$zahl = +$text;
$zahl = -$text; # Vorzeichen wurde negiert
$zahl = abs '-2d';# 2, Konvertierung zu natürlichen Zahlen
5.fmt("%b") # 0b101, konvertiert Dezimalzahl, analog zu prinf
:2(101) # 5, konvertiert Zahlen beliebiger Basis ins dekadische System
3 + 4; # 7, soll ich das erklären?
3 - 4; # -1,
3 * 4; # 12,
3 ** 4; # 81, 3 hoch 4
3 / 4; # 0.75,
6 div 4; # 3/2,
3 % 4; # 3, 3 durch 4 sind 0 Rest 3
3 mod 4; # dito
12 %% 4; # 1, 12 ist durch 4 teilbahr
3 +& 4; # 0, bitweises and
3 +| 4; # 7, bitweises or
3 +^ 5; # 1, bitweises xor
+^ 6; # -7, bitweises not
4 +< 1; # 8, links shiften
Die Operatoren mit dem
+ fallen sicher besonders auf das sie vollständig neu sind und ungewöhnlich aussehen. Dieses
+ darin hat aber genau die slebe bedeutung die ein einzelnes
+ vor einem Wert, es wandelt beide Operanden in den numerischen Kontext um und wendet dann den zweiten Teil dieser zusammengesetzen Operatoren an.
&,
|,
^, kenn man ja in seiner logischen Bedeutung und
> und
< sind nur verkürzte Formen der bekannten Shiftoperatoren
>> und
<<. Genau diese zusammengesetzten Operatoren gibt es auch für den boolschen (mit '?') und den Stringkontext (mit '~') nur das Shiften es halt im Ersten nicht geben kann und im Zweiten sehr gewöhnungsbedürftig ist.
numerische Auswahloperatoren
Neu sind auch die numerischen Auswahloperatoren:
$zahl = 5 min 7; # 5
$zahl = 5 max 7; # 7
$zahl = 5 max 7 max 11; # 11
Diese gibt es auch als Arraymethoden:
$min = min @zahlen; #
$max = @zahlen.max; #
($min, $max)= @a minmax @b; # min aus @a und max aus @b
Integer Kontext
Umfasst nur Zahlen ohne Nachkommastellen, hat soweit ich weiss keine eigenen Operatoren, nur den bereits aus Perl5 bekannten int() Befehl der bei Bedarf die Kommastellen abschneidet und so diesen Kontext herstellt.
String Kontext
Im Stringkontext, den man am '~' erkennt, werden Inhalte als Zeichenketten (String, englisch: Faden) betrachtet. Sie werden also Zeichen für zeichen so genommen wie zugewiesen, was man auch literal nennt. Zur Verdeutlichung: würde man im numerischen Kontext einer Variable
5.0 zuweisen, wäre ihr neuer Wert einfach
5. Im Stringkontext besteht jedoch
'5.0' aus 3 Zeichen ('5','.','0').
$string = ~$zahl; # wandelt in Stringkontext
'Ivan' ~ ' ist nicht zu hause.';# verknüpft Text (als 2 verbindende Arme vorstellbar)
cat('Ivan', ' ist nicht ...'); # alternative Schreibweise
'hi' x 7; # 'hihihihihihihihi'
'jj' ~& 'gg'; # 'bb'
'aa' ~| 'bb'; # 'cc'
'GG' ~^ "**"; # 'mm'
'd' ~< 1; # 'È', rechter operand ist immer Zahl
'tfahcstobmieheG'.flip # Geheimbotschaft ( sind meist nicht lange geheim :) )
Die letzten 4 Operatoren scheinen zuerst sehr seltsam, jedoch tun sie kaum etwas anderes als ihre numerischen Pendanten. Der einzige Unterschied: hier werden alle Zeichen einzeln intern mit
ord in Zahlen umgewandelt, dann die entsprechenden Operationen ausgeführt, und zum Schluß wieder zeichenweise mit
chr zurück verwandelt. Demnach entspricht
'd' ~< 1; den Operationen:
chr( ord('d') ~< 1 ), also
chr(100 << 1); Auch
flip fordert den Stringkontext. Es ist eine kleine, manchmal nützliche Funktion, mit dem vor allem Ruby-Tutorials prahlen (dort
reverse), jetzt auch in Perl.
Zuweisungsoperatoren
Da Zuweisung auch viel mit Variablen zu tun hat findet ihr das Thema in
Kapitel3?.
selbstzuweisende Operatoren
Fast allen Operatoren für den Skalarkontext, aber auch weiteren wie "**" kann rechts ein Gleichheitszeichen angehängt werden. Damit erhält man ein Konstrukt das genauso wie der jeweilige Operator funktioniert, aber das Ergebnis dem linken Operanden zuweist. Als Sonderform dessen kann man das Autoinkrement und Autodekrementsehen (++ und -- geschrieben) die je nachdem ob sie links oder rechts der Variable geschrieben werden vor oder nach dem Auswerten des Ausdrucks angewendet werden.
$zahl += 2; # wie $zahl = $zahl + 2;
$text x= 2; # = $text ~ $text;
$zahl++; # entspricht $zahl +=1 nach Auswerten des Terms
--$zahl; # andere Schreibweise für $var.=pred; (voriges $var.succ)
Die letzten beiden Operatoren sind wohlbekannt und dienen in Perl 6 einem viel allgemeinerem Mechanismus, der nur im numerisch-skalaren Spezialfall zu den bewährten Ergebnissen führt.
++ und
-- sind nun dafür da, den Nachfolger oder Vorgänger beliebiger Objekte zu bilden, sofern diese Methoden mitbringen die intern dazu aufgerufen werden können.
Reverse Operatoren
Der Metaoperator R (grosses R) funktioniert ebenso wie das "=" als metaoperator für Skalaroperationen. Er vertauscht die Operanden.
2 R- 5 # ergibt 3
Operatoren für Arrays
Arrayerzeugende Operatoren
@prim = 2,3,5,7,11,13,17; # Kommas erzeugen Arrays
@noten =<do re mi fa so le> # das neue qw()
@hexziffern = 0 .. 9,a .. f; # (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)
@ganze = 0 .. *; # Zahlenbereich N, unendliche lazy list
@ganze = 0 .. Inf; # dito
@gerade = 0 .. *:by(2); # alle geraden Zahlen
@zahlen = 1 .. 5:by(-1); # (5,4,3,2,1)
@zahlen = 5 .. 1; # leere liste
@zahlen = reverse 1..5; # (5,4,3,2,1); TIMTOWTDI
@zahlen = 1^..^7; # (2,3,4,5,6); ^ schliesst Grenzwert aus
@zahlen = ^5; # (0,1,2,3,4); schönes Kürzel für schleifen, 5mal halt
@wortanzeige= "Null" xx 3; # ('Null','Null','Null')
@zahlen = (1,2,3) xx 2; # (1,2,3,1,2,3)
@zahlen = (1,2) X (3,4); # (1,3), (1,4), (2,3), (2,4); einfacher Kreuzoperator
@zahlen = (1,2)X(3,4)X<a b>; # (1,3,a),(1,3,b),(1,4,a),(1,4,b),(2,3,a),(2,3,b),(2,4,a),(2,4,b)
@zahlen = zip([1,2],[3,5]); # (1,3,2,5); abwechselnd 1 element aus jedem
@zahlen = (1,2)zip(3,5); # (1,3,2,5); noch ne andere Schreibweise
@zahlen = (1,2)Z(3,5)Z(9,8); # (1,3,9,2,5,8); noch ne andere Schreibweise
@werte = push (^3), 10; # (0,1,2,10); fügt den Wert am Ende an
@zahlen = push (5,7), @werte;# (5,7,0,1,2,10); fügt Liste von Werten an
$zahl = pop @werte; # 10; holt letzten Arraywert, aber das ist doch alles wohlbekannt
Feed
Wenn man arraybearbeitende Befehle benutzt und diese schachtelt wie bei einer schwartz'schen Transformation, geht manchmal die Lesbarkeit verloren. Deswegen kann man jetzt mit den expliziten feed-Operatoren das Verhalten optisch klar rausstellen. Der Name
feed illustriert das die Daten nicht flüssig wie aus einer Leitung (pipe), sondern Stückchenweise wie beim füttern von einer Station zur nächsten weitergereicht werden.
@output = grep { $_ % 2 } @input; # bekannter Syntax, geht auch in Perl6
@output <== grep { $_ % 2 } <== @input; # so gehts jetzt auch
@input ==> grep { $_ % 2 } ==> @output; # und so auch
@in1 ==>> @in2 ==>> grep { $_%2 } ==> @out; # Beispiel mit 2 Quellen
Im letzten Beispiel "fließen" die Daten nicht nur in die andere Richtung sondern die Eingabe ergießt sich auch aus mehreren Arrays. Sobald @input1 alle Elemente weitergegeben hat, folgen die Elemente von @input2.
Hyperoperatoren
Sind normale Skalaroperatoren die auf jedes Element einer Liste angewandt werden, so daß dabei wieder eine Liste mit den Ergebnissen entsteht. Verlangt der eingesetzte Operator einen zweiten Wert, kann dazu ein Skalar oder ein weiterer Array verwendet werden. Bei letzterem werden immer die Werte mit gleichem Index miteinander verknüpft, bei Arrays unterschiedlicher Länge, orientiert sich der Operator am längeren Array und verwendet leere Werte statt nichtvorhandener Arrayelemente. Hyperoperatoren werden mit dem Unicodezeichen "Chevron" («») gekennzeichnet, in der ASCII-Variante << und >> geschrieben.
@zahlen = +<< @strings; # man kann fast jeden Operator nehmen
@gerade = @ungerade >> + 1; #
@modulo = @dividenden >>%<< @divisoren;
Kreuzoperatoren
Wie die vorigen Hyper- und die nachfolgenden Reduktionsoperatoren, sind dies ebenfalls Metaoperatoren, die es erlauben Skalaroperatoren auf Arrays anzuwenden. Der Kreuz-Hyperoperator ist dabei nur eine Erweiterung des schon bei den arrayerzeugenden Operatoren erwähnten, einfachen Kreuzoperators. Einen Kreuz-Hyperoperator erhält man, wenn man den gewählten Operator rechts neben ein
X stellt. Dieser wird dann auf alle möglichen Paare von Elementen zweier Arrays angewendet. Oder anders gesagt, er klappert alle Kombinationsmöglichkeiten von 2 Arrays ab, nimmt sich während jeder dieser Kombinationen ein Element von links und eins von rechts, stellt dazwischen den einfachen Operator der neben dem
X steht (keine Leerzeichen dazwischen), wertet den Ausdruck aus, und schiebt das Ergebnis in eine Pipe, sodaß das Ergebnis wieder ein Array ist.
(1, 2, 3) X* (2, 3) # ergibt (2, 3, 4, 6, 6, 9)
('a', 'b') X~ ('1','2') # ergibt <a1 a2 b1 b2>
Reduktionsoperatoren
Heissen so, weil sie meist aus einem Array (Input) einen Skalar (Output) machen. Dazu kann man fast beliebige Operatoren nehmen die 2 Werte zu einem Ergebnis verarbeiten, packt sie in eckige Klammern ("[]") und hat nun einen Reduktionsoperator, der sich das erste Paar Werte nimmt, dieses zum Ergebnis umwandelt, das mit dem nächsten Wert im Array das nächste Paar bildet. Ob dabei von "rechts" oder "links" angefangen wird hängt vom Assoziationsverhalten des Operators in der Klammer ab, da Reduktionsoperatoren dem normalen, verketteten Verhalten der Operatoren entspricht.
$summe = [+] @zahlen; # praktisch nicht, dasselbe wie:
$summe = [+] 1, 2, 3, 4; # 10 = ((1 + 2) + 3) + 4;
$potenz = [**]1, 2, 3; # 1 = 1 hoch (2 hoch 3);
$sortiert = [<] @zahlen; # 1 wenn array sortiert ist
$zahl = [||]@zahlen; # erster nichtleerer Wert
($min,$max)= [minmax] @a; # der kleinste und gröte Wert
Es gibt aber noch zwei altbekannte Reduktionsoperatoren die keine Hyperoperatoren sind.
$string = [~] @worte; # verkettet alle worte
$string = cat @worte; # so gehts auch
$string = join @worte; # so auch
$string = join ',', @worte;# worte sind durch Kommata getrennt
Von den Reduktions-Hyperoperatoren gibt es auch noch eine Variante, die noch etwas komplizierter ist, aber einmal verstanden sehr sehr nützlich sein kann. Besonders Mathematiker die Zahlenreihen generieren möchten, bei der ein Element vom vorigen abgeleitet wird, werden begeistert sein.
[\+] 1..5 # (1, 3, 6, 10, 15), dies entspricht:
([+] 1),
([+] 1, 2),
([+] 1, 2, 3),
([+] 1, 2, 3, 4),
([+] 1, 2, 3, 4, 5)
Vorrangtabelle
Findet ihr
hier in der Kurzreferenz.
eigene Operatoren
Wie schon erwähnt, sind für einen Perl 6-Interpreter alle Operatoren interne Methoden verschiedener Objekte. Und da Objekte auch zur Laufzeit neue Methoden bekommen können, ist es möglich Operatoren umzudefinieren oder neue zu formulieren. Es reicht lediglich das Wissen, unter welchem Namen Operatoren angesprochen werden. Dazu sollte man zuerst wissen, daß Perl 6 4 Klassen an Operatoren kennt. Die werden je nach relativer Position des Operators zum Wert oder Variable, auf die er sich bezieht, unterschieden. Präfix (vor dem Wert wie --$a) und Suffix (nach dem Wert wie $a++) sind vielleicht noch aus dem schulischen Deutschunterricht bekannt. Es gibt aber auch noch Infix (zwischen 2 Werten) und Circumfix (zweiteilige Operatoren, die sich wie Klammer um den Wert legen). Als zweites sollte man auch noch etwas über
Perl 6 Macros wissen, denn mit ihnen kann man zur Laufzeit die Sprache ändern. Als drittes wäre auch nützlich zu Wissen, welche Namen die Parameter automatisch bekommen, und dann können wir anfangen:
macro infix:<+> { $^a - $^b } # wir definiere das =+= in ein =-= um :)
macro prefix:<!> (int $n) { [*] 1..$n } # fakultät, nur negation gibts jetzt nicht mehr
macro circumfix:<[ ]> { say 'no arrayref in my language' }
Operatoren können nicht nur als Macros, sondern auch als normale Klassenmethoden definiert werden um den Umgang mit Objekten zu vereinfachen.
absichtlich nicht vorhandene Operatoren
Um Flüchtigkeitsfehler während der Umstellung von Perl 5 zu Perl 6 aufzuzeigen, geben folgende Operatoren immer eine Fehlermeldung aus:
-> wie in $var->{accessor}, jetzt $obj.accessor
oder $arrayref->[index], jetzt $arrayref[index]
Diesen Operator Bitte nur noch für
pointy subs benutzen.
=~ heißt nun ~~, was weniger leicht mit ~= verwechselt werden kann
!! doppelte logische verneinung ist illegal, überflüssig und unpraktisch da ternärer op jetzt ?? ... !! ... ist.
Übersicht ||
0:Vor |
1:Ge |
2:Theo |
3: Variablen |
4: Operatoren |
5: Ein- und Ausgabe |
6:{} |
7:Sub |
8:OOP |
9:Rx ||
A:Index |
B:Tab |
C:Tour |
D:Delta |
E:Links
--
HerbertBreunung - 30 Mar 2006
--
MoritzLenz - 26 Feb 2007