Perl 6
Perl 6 Variable Tablet: Revision 56

Overview - Chapter: 0:Intr, 1:Hist, 2:Design, 3:Var, 4:Op, 5:IO, 6:{}, 7:Sub, 8:OOP, 9:Rx - Appendices: A:Index, B:Tables, C:Best of, 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.

Primary Types

Perl 6 (as Perl 5) knows 3 basic types of variables: Scalars (single values), Arrays (ordered and indexed lists of several values) and Hashes (2 column table, with ID and associated value pairs). They can be easily distinguished, because in front of their name is a special character called sigil (latin for sign). Its the $ (similar to S) for Scalars, @ (like an a) for Arrays and a % (kv pair icon) for a Hash. They are now invariant, which means for instance, an array vaiable starts always with an @, even if you just want a slice of the content. The sigils mark also distinct namespaces, meaning: in one lexical scope you can have 3 different variables named $stuff, @stuff and %stuff. These sigils can also be used as an operator to enforce a context in which the following data will be seen.

The fourth namespace where you can store and retrieve something under specified names is the one of subroutines and alike, even if you don't might think of them as variables. It's sigil & has to be used only rarely.

Special namespaces of Perl 5 (often marked with special syntax) like tokens (__PACKAGE__), formats, file or dir handle and builtins are now regular (mostly scalar) variables or routines.

Because variables are (as anything in Perl 6) objects, they have methods. In fact, any operator, including these square or curly brackets you get specific array and hash values with, are just methods of a variable object with a fancy name.

Scalar

This type is known as a storage room for one value, but it's more like a reference that can point to anything: to values of any data type, to code, to objects or to a compound of values like a pair, junction, array or hash. The scalar context is now called item context hence the scalar instruction from Perl 5 was renamed to item.

$CHAPTER = 3;
$pi = 3.1415926;
$float = 6.02e23;
$text = 'Welcome all!';    # single quoted string
$text = "What is $pi?";    # double quoted string, does eval $pi
$text = q:to'EOT';         # Heredoc string
   handy for multiline text
EOT
$handle = open $file_name; # file handle
$object = Class::Name.new();
$arrayref = [0,1,1,2,3,5,8,13,21];
$hashref = {'audreyt'=>'pugs', 'pm'=>'pct', 'damian'=>'larrys evil henchman'};
$coderef = sub { do_something_completely_diffenent(@_) };

Unlike Perl 5, references are automatically dereferenced to a fitting context. So you could use these $arrayref and $hashref in same way as an array or hash, making $ the variable highlighter, pretty much like in PHP.

Array

is an ordered and indexed list of scalar variables. Their context is forced with a @ operator or list command. If not specified otherwise they can be changed, prolonged and shorten anytime and used as a list, stack, queue and much more. As in Haskell, lists are processed lazily, which means: the compiler looks only at the part he currently needs. This way Perl 6 can handle infinite lists or do computation on lists that are still building up. The lazy command enforces and the eager command prevents that behaviour on any expression.

@primes = (2,3,5,7,11,13,17,19,23); # an array gets filled
@primes =  2,3,5,7,11,13,17,19,23 ; # same thing, since () just do group
@primes = <2 3 5 7 11 13 17 19 23>; # dito, <> is the new qw()
$arrayref = 2,3,5,7,11,13,17,19,23; # in scalar context you get automatically a reference
$arrayref = 13,;                    # comma is the new array generator
@primes = 2;                        # array with one element
@primes = [2,3,5,7,11,13,17,19,23]; # array with one element (arrayref)
@dev    = {'dan' => 'parrot'};      # array with one element (hashref)
@data   = [1..5],[6..10],[11..15];  # Array of Arrays (AoA)

Array Slices

@primes                       # all values
"@primes[]"                   # insert all values in a string, use [] as distinction from mail adresses
$prime = @primes[0];          # get the first prime
$prime = @primes[*-1];        # get the last one
@some = @primes[2..5];        # get several
$cell = @data[1][2];          # get 8, third value of second value (list)
$cell = @data[1;2];           # same thing, shorten syntax
@numbers = @data[1];          # get a copy of the second subarray (6..10)
@copy = @data;                # copy the whole AoA, no more reference passing, use binding instead

Array Methods

Some of the more important things you can do with lists. All the methods can also used like ops in "elems @rray;"

+ @rray;             # numeric context does the same
@rray.elems;         # number of elements (like in Perl 5 scalar @a)
@rray.end;           # number of the last element, equal to @rray.elems-1
@rray.exists(@ind);  # Bool::True if all indecies of @ind have a value (can be 0 or '')
@rray.delete(@ind);  # delete all cell with indecies of @ind
~ @rray;             # in string context you get all content, stringified and joined
@rray.cat;           # does the same
@rray.join('');      # also same result, you can put another string as parameter that gets between all values
? @rray;             # Bool::True if array has any value in it, even if its a 0
@rray.unshift;       # prepend one value to the array
@rray.shift;         # remove the first value and return it
@rray.push;          # add one value on the end
@rray.pop;           # remove one value from the end and return it
@rray.splice($pos,$n)# remove on $pos $n values and replace them with values that follow that two parameter
@rray.pick([$n]);    # return $n (default is 1) randomly selected values, without duplication
@rray.roll([$n]);    # return $n (default is 1) randomly selected values, duplication possible (like roll dice)
@rray.reverse;       # all elements in reversed order
@rray.rotate($n);    # returns a list where $n times first item is taken to last position if $n is positive, if negative the other way around
@rray.sort($coderef);# returns a sorted list by a userdefined criteria, default is alphanumerical sorting
@rray.min;           # numerical smallest value of that array
@rray.max;           # numerical largest value of that array
$a,$b= @rray.minmax; # both at once, like in .sort . min or .max a sorting algorith can be provided 
@rray.map($coderef); # high oder map function, runs $coderef with every value as $_ and returns the list or results
@rray.classify($cr); # kind of map, but creates a hash, where keys are the results of $cr and values are from @rray
@rray.grep({$_>1});  # high order grep, returns only these elements that pass a condition ($cr returns something positive)
@rray.first($coder); # kind of grep, return just the first matching value
@rray.zip;           # join arrays by picking first element left successively from here and then there

There is even a whole class of metaoperators that work upon lists.

Hash

is in Perl 6 an unordered list of Pairs. A Pair is a single key => value association and appears in many places of the language syntax.

%dev =  'pugs'=>'audreyt', 'pct'=>'pm', "STD"=>'larry';
%dev = :rakudo('jnthn'), :testsuite('moritz');            # adverb (pair) syntax works as well
%dev = ('audreyt', 'pugs', 'pm', 'pct', 'larry', "STD");  # lists get autoconverted in hash context
%compiler = Parrot => {Rakudo => 'jnthn'}, SMOP => {Mildew => 'ruoso'};       # hash of hashes (HoH)

Hash Slices

my $table = %dev;          # nicely formatted 2 column table using \t and \n
say %dev;                  # only $key and $value are separated by \t

 ~ %dev                    # string context, same thing
 ? %dev                    # bool context, true if hash has any pairs
 + %dev                    # numeric context, returns number of pairs(keys)

$value = %dev{'key'};      # just give me the value related to that key, like in P5
$value = %dev<pm>;         # <> autoquotes like qw() in P5
$value = %dev<<$name>>;    # same thing, just with eval
@values = %dev{'key1', 'key2'};
@values = %dev<key1 key2>;
@values = %dev<<key1 key2 $key3>>;

%dev\ .{'patrick'};        # "long dot style", because its its an object in truth 
%dev   {'audrey'};         # error, only syntax before will work
%dev\  {'allison'};        # works,
%dev   .<dukeleto>;        # error

%compiler<Parrot><Rakudo>; # value in a HoH, returns 'jnthn'
%compiler<SMOP>;           # returns the Pair: Mildew => 'ruoso'

Hash Methods

%dev.keys                  # returns the list with all keys
%dev.values                # list of all values
%dev.kv                    # flat list with key1, value1, key 2 ...
%dev.pairs                 # list of pair objects, list context default (same as in @a = %dev) 
%dev.invert                # reverse all key => value relations    

Callable

Internally subroutines, methods and alike are variables with the sigil "&" and stored in a fourth namespace. They are no more builtins with an own namespace, that can't be overwritten or augmented with your programming.

Object Types

Perl 6 has much more variable types then the primary 4. They are defined by classes or partial classes (roles).


In fact you can use arrays and hashes from a scalar like an array or hash itself (Perl dereferes automatically). Then a $ marks every variable like in PHP.

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):

On a deeper level
There are lot more types without own namespaces (usually stored in a scalar) like pairs or capture. Most of them have a sigil which also works as an operator to that type context. After the sigil ($, @ or %) they can also have a secondary sigil, that signals special namespaces, often used by special variables.

object types

Pair

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.

$pair = 'key' => 'value'; # "=>" is der Paarkonstruktor
$pair = :key('value'); # andere Schreibweise

Scalar Context

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), ist nun das selbe wie :
$arrayref = [0,1,1,2,3,5,8,13,21]; # was immernoch das selbe ist wie :
$arrayref = \(0,1,1,2,3,5,8,13,21); # aber:
$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
$subref = sub {'audrey', 'pugs', 'leo', 'parrot'}; # ref auf sub die ne liste liefert
$subref = {'audrey', 'pugs', 'leo', 'parrot'}; # das selbe, {} machen immer einen block

$arrayref = 13,;                      # comma is the new array generator
$pairlistref = ('larry'=>'STD', 'ruoso'=>'SMOP', 'flavio'=>'Perlito');
$coderef = {'jnthn', 'pm', 'masak'};  # sub returning a list


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.

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 usw. werden ebenfalls optional als Arraymethoden aufrufbar.

Arraykontext

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', 'leo'=>'parrot', 'damian'=>"larry's evil henchman");
%perl6leute = ('audrey', 'pugs', 'leo', 'parrot', 'damian', "larry's evil henchman"); # geht auch
%perl6leute = ('Flavio' p5=> 'kp6', 'will' p5=>'parrot', 'pmichaud' p5=> 'pct'); # sogar das

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

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

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 eine Referenz auf eine Suboutinen-Signatur. Da Parameter nach Position geordnet oder Namen haben können, erscheinen Capture am Anfang als eigenwillige Mischform aus Array und Hash. Da eine Capture normal mit einem $ anfängt, also ein Zeiger einzelner Zeiger auf eine solche Struktur ist, löst sie auch die Perl 5-Referenzen ab. Auch die bereits vorgestellten Referenzen auf Arrays oder Hashes sind in Wirklichkeit Capture, die wissen wie man sich dem Kontext gemäß zu verhalten hat. Im einfachsten Falle sind Syntax und Verhalten einer Referenz auf eine einfache Variable dem von Perl 5 gleich. Dies ist nur ein vereinfachter Sonderfall. Capture können sehr viel mehr, wie die folgenden Beispiele zeigen: (Der senkrechte Strich dereferenziert eine Capture.)

my $cap1 = \$x; # die einfachste Capture
my $args = \($fh: "Hi!"); # ein benannter Parameter mit Inhalt
sub routine (|$args) { ... } # fütter damit eine sub

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.

Assignment and Binding

Assignment

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; # Perl5 schreibweise, geht immernoch, Originalwert in $$spiegel
$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. Mit our deklarierte Variablen werden in die Symboltabelle des aktuellen package eingetragen und sind über den Packagenamen auch von ausserhalb zugreifbar. Globale Variablen werden mit einer sekundären Sigil * gekennzeichnet.

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

Types

Es ist eine von Perls Stärken, daß Datentypen wie int, char, real u.s.w. alle in Skalare passen und bei Bedarf automatisch konvertiert werden (siehe oben und kontexterzeugende Skalaroperatoren). Dies hilft Programme schnell und sorglos zu schreiben, zu Lasten der Systemressourcen. Deswegen ermöglicht Perl6 jetzt auch Variablen zu typisieren und damit - wo nötig - Speicherverbrauch verringert und Geschwindigkeit erhöht werden kann. Wird z.B. in einem Algorithmus eine Variablen nur als Integer verwendet, kann diese auch zu Begin als Int deklariert werden und der Interpreter kann entsprechend optimieren. 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 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 Typentabelle 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;

Properties and 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

Special Variables

are listed here


Overview - Chapter: 0:Intr, 1:Hist, 2:Design, 3:Var, 4:Op, 5:IO, 6:{}, 7:Sub, 8:OOP, 9:Rx - Appendices: A:Index, B:Tables, C:Best of, D:Delta, E:Links


Upload Files

Click "Browse" to find the file you want to upload. When you click "Upload file" your file will be uploaded and added to the list of attachments for this page.

Maximum file size: 50MB

 
 
 
File Name Author Date Uploaded Size

Save Page As

Enter a meaningful and distinctive title for your page.

Page Title:

Tip: You'll be able to find this page later by using the title you choose.

Page Already Exists

There is already a page named XXX. Would you like to:

Save with a different name:

Save the page with the name "XXX"

Append your text to the bottom of the existing page named: "XXX"

Upload Files

Click "Browse" to find the file you want to upload. When you click "Add file" this file will be added to the list of attachments for this page, and uploaded when you save the page.

 
 
 
Add Tags

Enter a tag and click "Add tag". The tag will be saved when you save the page.

Tag: 

Suggestions: