You are here: Wissensbasis Web>PerlTafelKapitel2?>Perl6TafelVariablen (2010-11-19)

Übersicht || 0:Vor | 1:Ge | 2: Theorie | 3: Variablen | 4: Operatoren | 5:IO | 6:{} | 7:Sub | 8:OOP | 9:Rx || A:Index | B:Tab | C:Tour | D:Delta | E:Links

Allison Randal: The most basic building blocks of a programming language are its nouns, the chunks of data that get sucked in, pushed around, altered in various ways, and spat out to some new location.

Primäre Datentypen

Skalare

Skalare fangen immer noch mit $ an ($ wie S wie Skalar) und sind immer noch einfache Variablen die alles speichern können, eigentlich Referenzen die auf alles zeigen können, solang es nur eine Sache auf einmal ist:

    $TEXT     = "Seid Willkommen!";
    $kapitel  = 3;
    $pi       = 3.1415926;
    $arrayref = [0,1,1,2,3,5,8,13,21];
    $hashref  = {'audrey'=>'pugs', 'leo'=>'parrot', 'damian'=>'larrys evil henchman'};
    $coderef  = sub { print "$_\n" };  # ruf die sub mit $coderef($text);
    $obj      = Classname.new;
    $handel   = open $datei_name;

Ja ihr habt richtig gesehen, file & dirhandler als auch formate haben keinen eigenen Namespace mehr, denn es sind jetzt Objekte auf die wir ja mit einem Skalar zugreifen. Und die Coderef im Beispiel ist auch überflüssig, weil genau das jetzt der aus REXX übernommene say Befehl macht, der wohl auch in Perl 5.10 eingeführt wird. Selbstverständlich kann man in einem Skalar auch rules, junctions, formate und alles was hier sonst so vorgestellt wird speichern, wie auch Paare (neuer Datentyp):

Skalarkontext

Ausser Skalaren gibt es in Perl6 nur noch Arrays, Hashes und Captures, einer Mischung aus beidem. Wenn man sie einem Skalar zuweist, wird dem Skalar eine Referenz (Zeiger) darauf zugewiesen, weil Perl immer versucht das Ergebnis in die erwartete Form (in den Kontext) zu bringen. Obiges Beispiel hätte man also auch so schreiben können:

    $arrayref =  (0,1,1,2,3,5,8,13,21); # Fibonacci Reihe - Liste, nicht änderbar
    $arrayref = \(0,1,1,2,3,5,8,13,21); # Capture, nicht änderbar
    $arrayref =  [0,1,1,2,3,5,8,13,21]; # Array, änderbar
    $zahl     = (13);  # das bleibt Skalar, weil Klammern dienen nur zum Gruppieren
    $arrayref = (13,); # das Komma ist der Array-Operator, oder :
    $arrayref = [13];  # wenn es nur ein element haben soll
    $pairlistref = ('audrey'=>'pugs', 'leo'=>'parrot', 'damian'=>'larrys evil henchman');
    $hashref  = {'audrey'=>'pugs', 'leo'=>'parrot'};     # "=>" ist hash konstruktor
    $hashref  = hash {'audrey', 'pugs', 'leo', 'parrot'};# hash ist wie sub ein keyword
    $hashref  = pair {'audrey', 'pugs', 'leo', 'parrot'};# pair auch
    $subref   = sub {'audrey', 'pugs', 'leo', 'parrot'}; # ref auf sub die ne liste liefert
    $subref   = {'audrey', 'pugs', 'leo', 'parrot'};     # das selbe, {} machen immer einen block

Damit ist es möglich in perl 6 wie in php für alles Variablen mit einer $ am Anfang zu benutzen, aber man muß es zum Glück nicht.

Skalartypen

Aber selbst wenn nur ein einzelner Wert in einem Skalar ist, kann dieser einen Datentyp haben und in andere umgewandelt werden. Die 3 wichtigsten dieser Typen (mit dem entsprechenden Operator der ihn erzeugt) sind Bool ( ?), Num [eric] ( +) und Str [ing] ( ~). Mehr dazu hier. Während diese Typen auch als Konetxt gelten (numerischer Kontext), gibt es noch viele weitere optionale Datentypen für Skalare wie int, char, real u.s.w. Dabei kann der Anfangsbuchstabe des Types groß oder klein geschrieben werde. In der Kleinschreibung wird auf den Typ optimiert, aber Zuweisungen anderer Typen bleiben mit Geschwindigkeitsverlust möglich. Bei Großschreibung werden Typen fixiert, jede typenfremde Operation erzeugt dann eine Fehlermeldung. Eine grosse Platzersparnis können auch sogenannte "packed Arrays" sein, denn wenn ich 10.000 Werte speichern will, die alle nicht grösser als 15 werden, kann ich den Array auch als int4 typisieren, also als 4-Bit Integer. Damit spare ich nicht nur den Speicher für die String-Representation aller 10.000 Werte sondern kann auch jetzt 16 Werte speichern, wo vorher nur einer hingepasst hätte. (siehe auch Varaiblentypent im Anhang B)
    my Int $scalar;
    my int $scalar;
    my Array of Int %hash;
    my buf @buffers;
    my ref[Array] @ragged2d;

    my Dog $spot = Dog.new( );
    our Int $pi = 3;
    my int @array;
    my str @array;
    my bit @array; 

Subtypen

Von gegebenen Typen können auch Untermengen als neue Typen definiert werden. Strenggenommen macht man dies mit einer Subroutine mit besunderem Syntax die Bool::True (1) zurückliefert wenn der gegebene Wert Teil der Menge ist.

    subset Num+ of Num where { $_ > 0 };

Ein Paar

Paare sind praktisch die Bausteine eines Hashes (weiter unten), den man auch als Array(Liste) von Paaren sehen kann. Ein einzelnes Paar kann man wie folgt definieren.

    my $pair = 'key' => 'value'; # "=>" is der Paarkonstruktor
    my $pair = :key('value');    # andere Schreibweise
    my $pair = :key<value>;      # oder so
    $pair.isa(Pair)              # ergibt Bool::True
    $pair.key                    # 'key'
    $pair.value                  # 'value'

Arrays

Beginnen mit @ und sind immer noch dynamische Listen, gefüllt mit Skalaren. Ebenso wie Skalare, erzwingt ein Array links des "=" den Listkontext (wobei wir noch flattening, nonflattening und lazy Listkontexte kennenlernen werden).

    @primzahlen =  2,3,5,7,11,13,17,19,23 ; # array wird befüllt
    @primzahlen = (2,3,5,7,11,13,17,19,23); # ergebnisgleich, da () gruppieren
    @primzahlen = <2 3 5 7 11 13 17 19 23>; # dito, <> ist das neue qw()
    @primzahlen =  2;                       # array mit einem element
    @primzahlen = [2,3,5,7,11,13,17,19,23]; # array mit einem element (arrayref)
    @primzahlen = {'dan' => 'parrot'};      # array mit einem element (hashref)

Was sich geändert hat ist, das Arrays jetzt IMMER mit @ beginnen selbst wenn ich nur auf einzelne Elemente zugreifen will. Neu ist auch das Arrays Objekte mit eigenen Methoden sind:

           Perl5                     Perl6              

    $primzahlen[1];               @primzahlen[1];         # zweites Element
    @{$ref->[1][2]{"a"}}[1,2,3];  $ref[1][2]{"a"}[1,2,3]; # Teilarray, kein deref wegen strikter Sigils
    @rray; (im skalarkontext)     @rray.elems;            # Anzahl der Elemente
    $#rray;                       @rray.end;              # nummer des letzten Elements (@rray.elems-1)
    $rray[-1];                    @rray[*-1];             # Inhalt des letzten Elementes
    "@rray"                       "@rray[]"               # alle Elemente einfügen

Arraymethoden

Auch gestandene Perl5 Arraybefehle wie reverse, sort, map usw. werden ebenfalls optional als Arraymethoden aufrufbar.

Arraykontext

In diesem Wird wird der Wert in einen Array umgewandelt, selbst wenn dieser nur einen oder keinen Wert haben sollte. Er mit dem Operator @, dem Blockmodifikator for oder bestimmten Befehlen wie map und grep erzwungen.

Slicekontext

Slices sind Teilstücke eines Arrays und der Slicekontext meint einen Arraykontext in dem die Elemente des Arrays auch Slices sein können. Der Slicekontext wird mit @@ erzwungen;

    $AoA = [1..3], [4..6];
    dump  @($AoA);        # entspricht 1..6
    dump @@($AoA);        # [1..3], [4..6]

Arraytypen

Perl 6 kennt optionale Datentypen wie Num, Str, Bool für Skalare aber auch Typen für Arrays. Eine List ist dabei eine unveränderbare Aufzählung mit signifikanter Reihenfolge, die allerdings so spät wie möglich evaluiert wird (lazy list). Ist sie bereits evaluiert nennt man es im P6-Jargon Seq (ence). Eine Sequenz, bei der die Reihenfolge der Elemente keine Rolle spielt heißt Set und wenn einzelne Werte mehrfach vorkommen ist es ein Beutel ( Bag ). Junctions werden als Sets mit besonderen Eigenschaften gesehen.

Hashes

Erkennt man an der %-Sigil, die nun auch konsistent ist. Wie angedeutet sind Hashes nun Listen anonymer Paare, die ihren eigenen Hashlistkontext erzwingen können.

    %perl6leute = ('audrey'=>'pugs', 'dan'=>'parrot', 'damian'=>"larry's evil henchman");
    %perl6leute =  :audrey('pugs'),  :dan('parrot'),  :damian("larry's evil henchman";    # geht auch - Adverbialnotation
    %perl6leute = ('audrey', 'pugs', 'dan', 'parrot', 'damian', "larry's evil henchman"); # Konvertierung von Listen im Hashkontext

Letzte Version ist für Coder die es unbedingt kompatibel haben wollen. Nun gibt es noch mehr Formulierungsmöglichkeiten, per Hashschlüssel zu den einzelnen Werten zu kommen.

    %perl6leute{'audrey'};         # ergibt pugs
    %perl6leute<audrey>;           # kürzere Schreibweise
    %perl6leute{"audrey"};         # eval Variante, denn statt text könnte auch Skalar innerhalb () stehen
    %perl6leute{$audrey};          # 
    %perl6leute<<$audrey>>;        # kürzere Schreibweise, geht auch mit Chevron Symbolen aus Unicode ("<<")
    %perl6leute<<audrey leo>>;     # liefert den array: ('pugs', 'parrot')
    %perl6leute\  .{'audrey'};     # Schreibweise: "long dot", denn eigentlich ist es ja ein Objekt
    %perl6leute    {'audrey'};     # Error, nur vorige Schreibweise gültig
    %perl6leute\   {'audrey'};     # Error, 
    %perl6leute    .<audrey>;      # Error

Hashmethoden

Hashes haben jetzt ebenfalls eigene Methoden, die z.B. wichtig werden, wenn wir damit Arrays füllen wollen.

    @leute    = %perl6leute.keys;  # ('audrey', 'leo', ...)
    @aufgaben = %perl6leute.values;# ('pugs', 'parrot', ...)
    @flatlist = %perl6leute.kv;    # a la perl5 = ('audrey', 'pugs', ...)
    @pairlist = %perl6leute.pairs; # (paar1, paar2, )
    @pairlist = %perl6leute;       # das gleiche, implizit
    %p6p = %perl6leute.invert;     # ('pugs' => 'audrey', 'parrot' => 'dan' )

Hashtypen

Capture

Dies ist wohl eine der härtesten Nüsse unter den Perl6 Neuerungen, da sich weder in Perl5 noch in anderen Sprachen vergleichbares findet. Grob gesagt ist eine Capture ein Datentyp der alle Parameter enthalten kann, die auf einmal einer Routine übergeben werden. Da Signaturen in Perl 6 gleichzeitig positionale und benannte Parameter haben können, kann eine Capture in Arraykontext(@) die Positionalen, im Hashkontext(%) die benannten und im Capturekontext(|) beides abgeben. Im Gegensatz zu Arrays und Hashes kann eine Capture, nach der Zuweisung nicht mehr verändert werden. Einem Skalar kann aber natürlich jederzeit eine neue Capture zugewiesen werden.
    my $cap1 = \$x;                 # die einfachste Capture
    my $args = \($fh: "Hi!");       # ein benannter Parameter mit Inhalt
    routine(|$args);                # fütter damit eine sub
Auch wenn Capture mit dem gleichen Syntax gebildet wird wie früher die Referenzen, enthalten sie wie andere Variablen nur Werte. Es gibt auch eigentlich keine Referenzen und Typeglobs mehr. Wer diese Funktionalität benötigt findet ähnliches im Kapitel Binding.

sekundäre Sigil

Wirklich neu in Perl6 ist auch, daß Variablen nach der primären Sigil ($, % oder @), die den Datentyp angibt, nun auch optional eine sekundäre Sigil (auch Twigil [tweak + sigil] genannt) haben können die einen speziellen Namensraum oder Variableneigenschaften markiert. Sie sind im einzelnen im Anhang B aufgeführt und erklärt.

Zuweisungen und Binding

Zuweisungen

Wie eben schon gezeigt, können sich Variablen mit dem einfachen Gleichheitszeichen ("=") ihre Inhalte gegenseitig zugeweisen. In deutsch: der Inhalt der rechten wird in die linke Variable kopiert. Dabei ist egal welchen Typ sie haben, solang beide Typen gleich sind:

    $kopie  = $original; 
    @kopien = @originale;
    %kopie  = %original; 
    $kopie2 = $kopie1 = $original; 
    @kopien = ($original1, $original2);
   (@kA, @kB) = (@orig_A, @orig_B); 

Binding

Doch manchmal möchte man, das 2 Variablen immer den Selben Inhalt haben, egal welche von beiden ich grad verändere (beide Variablennamen sind dann Aliase auf die selbe Variable). Perl6 spricht dann von einem Binding das über die interne Symboltabelle geschieht.

      $spiegel := $original;        # Perl6 binding zwischen 2 Skalaren
$spg2 := $spg1 := $orig;            # 2 Spiegel auf eine dritte Variablen
($spg1, $spg2) := ($orig1, $orig2); # man kann auch 2 Variablen auf einmal binden
($spg1, $spg2) := ($orig1);         # ERROR, Anzahl muss gleich sein
($s1, @s2 %s3) := ($o1, @o2, %o3);  # alle Typen kann man an Variablen gleichen Typs binden
     $spiegel ::= $original;        # Perl6 binding zur Kompilierungszeit
     $spiegel =:= $original;        # prüft ob die beiden Variablen aneinander gebunden sind
     $spiegel!=:= $original;        # negierte Form

Scope

Variablen, denen man bei der ersten Erwähnung ein my voranstellt, sind lexikalische Variablen, weil ihre Lebensdauer auf den akuellen lexikalischen Bereich (aktueller Block) begrenzt ist. Dies gilt nun ohne Ausnahmen. state ist eine Variante von my die schon in Perl 5.10 eingeführt wurde und es einfacher macht Closures zu schreiben. Mite state deklarierte Variablen sind außerhalb ihres lexikalischen Geltungsbereiches (Blocks) unsichtbar, behalten aber ihren Inhalt bis zum nächsten Eintritt in dieses Block und werden im Gegensatz zu my - Variablen dann nicht wieder initialisiert. Was früher loacal hieß, wird jetzt mit temp deklariert: eine Variable die bis zum Ablauf des aktuellen Blocks exisitiert (auch wenn zwischendurch woandershin gesprungen wird) und dabei gleichnamige package-Variablen überschattet. Mit our deklarierte Variablen werden in die Symboltabelle des aktuellen package (oder module oder class) eingetragen und sind über den Packagenamen auch von ausserhalb zugreifbar. Globale Variablen werden mit einer sekundären Sigil * gekennzeichnet, die in vielen Fällen optional ist.

    my $var;
    state
    temp
    let
    our $var;
    $*var;

Eigenschaften und Traits

Neu in Perl 6 ist auch, daß Variablen zusätzliche Eigenschaften erhalten können. Diese werden traits genannt, wenn sie mit is zur Startzeit des Programmes (compiletime) definiert werden oder properties wenn sie mit but zur Laufzeit (runtime) verändert werden.

    constant $pi  = 3.14159;
    $true_value = 0 but true;
    my @array is dim(2,5,42);       # Größe der Dimensionen festlegen

Spezialvariablen

sind hier gelistet


Übersicht || 0:Vor | 1:Ge | 2: Theorie | 3: Variablen | 4: Operatoren | 5:IO | 6:{} | 7:Sub | 8:OOP | 9:Rx || A:Index | B:Tab | C:Tour | D:Delta | E:Links

-- HerbertBreunung - 30 Mar 2006
Topic revision: r89 - 2010-11-19 - 20:09:16 - HerbertBreunung
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.