Perl Language
Variabelen
Zoeken…
Syntaxis
- mijn # Lexicale verklaring
- onze # Global-verklaring
- $ foo # Scalar
- @foo # Array
- $ # foo # Array Last-Index
- % foo # Hash
- $ {$ foo} # Scalaire de-referentie
- @ {$ foo} # Array De-Reference
- $ # {$ foo} # Array-DeRef Laatste-index
- % {$ foo} # Hash de-Reference
- $ foo [$ index] # Matrix wordt geïndexeerd
- $ {$ foo} [$ index] # Array De-Reference en geïndexeerd worden.
- $ foo -> [$ index] # Array De-Reference en geïndexeerd worden (vereenvoudigd)
- $ foo {$ key} # Hash krijg waarde voor key
- $ {$ foo} {$ key} # Hash Dereference en krijg waarde voor sleutel
- $ foo -> {$ key} # Hash Dereference en krijg waarde voor sleutel (vereenvoudigd)
- \ $ x # Referentie naar Scalar
- \ @x # Referentie naar array
- \% x # Referentie naar Hash
- = [] # Referentie naar Anonieme Array (Inline)
- = {} # Referentie naar anonieme hash (inline)
scalars
Scalars zijn het meest basale gegevenstype van Perl. Ze zijn gemarkeerd met het teken $
en hebben een enkele waarde van een van de drie typen:
- een nummer (
3
,42
,3.141
, enz.) - een string (
'hi'
,"abc"
, etc.) - een verwijzing naar een variabele (zie andere voorbeelden).
my $integer = 3; # number
my $string = "Hello World"; # string
my $reference = \$string; # reference to $string
Perl converteert snel tussen getallen en reeksen, op basis van wat een bepaalde operator verwacht.
my $number = '41'; # string '41'
my $meaning = $number + 1; # number 42
my $sadness = '20 apples'; # string '20 apples'
my $danger = $sadness * 2; # number '40', raises warning
Bij het omzetten van een string in een nummer, neemt Perl zoveel mogelijk cijfers van de voorkant van een string - vandaar waarom 20 apples
worden omgezet in 20
in de laatste regel.
Afhankelijk van of u de inhoud van een scalair als een tekenreeks of een nummer wilt behandelen, moet u verschillende operatoren gebruiken. Meng ze niet.
# String comparison # Number comparison
'Potato' eq 'Potato'; 42 == 42;
'Potato' ne 'Pomato'; 42 != 24;
'Camel' lt 'Potato'; 41 < 42;
'Zombie' gt 'Potato'; 43 > 42;
# String concatenation # Number summation
'Banana' . 'phone'; 23 + 19;
# String repetition # Number multiplication
'nan' x 3; 6 * 7;
Als u probeert stringhandelingen op getallen te gebruiken, worden er geen waarschuwingen gegenereerd; proberen om nummerbewerkingen op niet-numerieke tekenreeksen te gebruiken. Houd er rekening mee dat sommige niet-cijferige tekenreeksen zoals 'inf'
, 'nan'
, '0 but true'
als getallen tellen.
arrays
Arrays slaan een geordende reeks waarden op. U hebt toegang tot de inhoud per index of itereert erover. De waarden blijven in de volgorde waarin u ze hebt ingevuld.
my @numbers_to_ten = (1,2,3,4,5,6,7,8,9,10); # More conveniently: (1..10)
my @chars_of_hello = ('h','e','l','l','o');
my @word_list = ('Hello','World');
# Note the sigil: access an @array item with $array[index]
my $second_char_of_hello = $chars_of_hello[1]; # 'e'
# Use negative indices to count from the end (with -1 being last)
my $last_char_of_hello = $chars_of_hello[-1];
# Assign an array to a scalar to get the length of the array
my $length_of_array = @chars_of_hello; # 5
# You can use $# to get the last index of an array, and confuse Stack Overflow
my $last_index_of_array = $#chars_of_hello; # 4
# You can also access multiple elements of an array at the same time
# This is called "array slice"
# Since this returns multiple values, the sigil to use here on the RHS is @
my @some_chars_of_hello = @chars_of_hello[1..3]; # ('H', 'e', 'l')
my @out_of_order_chars = @chars_of_hello[1,4,2]; # ('e', 'o', 'l')
# In Python you can say array[1:-1] to get all elements but first and last
# Not so in Perl: (1..-1) is an empty list. Use $# instead
my @empty_list = @chars_of_hello[1..-1]; # ()
my @inner_chars_of_hello = @chars_of_hello[1..$#chars_of_hello-1]; # ('e','l','l')
# Access beyond the end of the array yields undef, not an error
my $undef = $chars_of_hello[6]; # undef
Arrays zijn veranderlijk:
use utf8; # necessary because this snippet is utf-8
$chars_of_hello[1] = 'u'; # ('h','u','l','l','o')
push @chars_of_hello, ('!', '!'); # ('h','u','l','l','o','!','!')
pop @chars_of_hello; # ('h','u','l','l','o','!')
shift @chars_of_hello; # ('u','l','l','o','!')
unshift @chars_of_hello, ('¡', 'H'); # ('¡','H','u','l','l','o','!')
@chars_of_hello[2..5] = ('O','L','A'); # ('¡','H','O','L','A',undef,'!') whoops!
delete $chars_of_hello[-2]; # ('¡','H','O','L','A', '!')
# Setting elements beyond the end of an array does not result in an error
# The array is extended with undef's as necessary. This is "autovivification."
my @array; # ()
my @array[3] = 'x'; # (undef, undef, undef, 'x')
Ten slotte kunt u de inhoud van een array herhalen:
use v5.10; # necessary for 'say'
for my $number (@numbers_to_ten) {
say $number ** 2;
}
Bij gebruik als booleans zijn arrays waar als ze niet leeg zijn.
hashes
Hashes kunnen worden opgevat als opzoektabellen. U krijgt toegang tot de inhoud door voor elk ervan een sleutel op te geven. Sleutels moeten tekenreeksen zijn. Als ze dat niet zijn, worden ze omgezet in tekenreeksen.
Als je de hash gewoon een bekende sleutel geeft, zal het je zijn waarde dienen.
# Elements are in (key, value, key, value) sequence
my %inhabitants_of = ("London", 8674000, "Paris", 2244000);
# You can save some typing and gain in clarity by using the "fat comma"
# syntactical sugar. It behaves like a comma and quotes what's on the left.
my %translations_of_hello = (spanish => 'Hola', german => 'Hallo', swedish => 'Hej');
Let in het volgende voorbeeld op de haakjes en het teken: u opent een element van %hash
met $hash{key}
omdat de gewenste waarde een scalaire waarde is. Sommigen vinden het een goede gewoonte om de sleutel te citeren, terwijl anderen deze stijl visueel luidruchtig vinden. Citeren is alleen vereist voor sleutels die kunnen worden aangezien voor uitdrukkingen zoals $hash{'some-key'}
my $greeting = $translations_of_hello{'spanish'};
Terwijl Perl standaard zal proberen barewords als tekenreeksen te gebruiken, kan +
modifier ook worden gebruikt om aan Perl aan te geven dat de sleutel niet moet worden geïnterpoleerd maar moet worden uitgevoerd met het resultaat van uitvoering als een sleutel:
my %employee = ( name => 'John Doe', shift => 'night' );
# this example will print 'night'
print $employee{shift};
# but this one will execute [shift][1], extracting first element from @_,
# and use result as a key
print $employee{+shift};
Net als bij arrays hebt u tegelijkertijd toegang tot meerdere hash-elementen. Dit wordt een hash-plak genoemd . De resulterende waarde is een lijst, dus gebruik de @
sigil:
my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')
Herhaal de toetsen van een hash met de keys
keys
zullen items in een willekeurige volgorde retourneren. Combineer met sort
als u dat wenst.
for my $lang (sort keys %translations_of_hello) {
say $translations_of_hello{$lang};
}
Als u de toetsen niet echt nodig hebt, zoals in het vorige voorbeeld, retourneert values
de values
de hash direct:
for my $translation (values %translations_of_hello) {
say $translation;
}
U kunt ook een while-lus te gebruiken met each
te herhalen over de hash. Op deze manier krijgt u zowel de sleutel als de waarde tegelijkertijd, zonder een afzonderlijke waarde opzoeking. Het gebruik ervan wordt echter afgeraden, omdat each
op een verkeerde manier kan breken.
# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
say $translation;
}
Toegang tot uitgeschakelde elementen retourneert undef, geen fout:
my $italian = $translations_of_hello{'italian'}; # undef
map
en lijstafvlakking kunnen worden gebruikt om hashes van arrays te maken. Dit is een populaire manier om een 'set' waarden te maken, bijvoorbeeld om snel te controleren of een waarde in @elems
. Deze bewerking duurt meestal O (n) tijd (dat wil zeggen evenredig met het aantal elementen) maar kan in constante tijd (O (1)) worden gedaan door de lijst in een hash te veranderen:
@elems = qw(x y x z t);
my %set = map { $_ => 1 } @elems; # (x, 1, y, 1, t, 1)
my $y_membership = $set{'y'}; # 1
my $w_membership = $set{'w'}; # undef
Dit vereist enige uitleg. De inhoud van @elems
wordt gelezen in een lijst, die wordt verwerkt door een map
. map
accepteert een codeblok dat wordt aangeroepen voor elke waarde van de invoerlijst; de waarde van het element is beschikbaar voor gebruik in $_
. Ons codeblok retourneert twee lijstelementen voor elk invoerelement: $_
, het invoerelement en 1
, slechts een waarde. Nadat u rekening hebt gehouden met het afvlakken van de lijst, is het resultaat dat map { $_ => 1 } @elems
qw(xyxzt)
in (x => 1, y => 1, x => 1, z => 1, t => 1)
.
Naarmate die elementen in de hash worden toegewezen, worden oneven elementen hashsleutels en worden zelfs elementen hashwaarden. Wanneer een sleutel meerdere keren wordt gespecificeerd in een lijst die moet worden toegewezen aan een hash, wint de laatste waarde. Hiermee worden duplicaten effectief verwijderd.
Een snellere manier om van een lijst een hash te maken, maakt gebruik van toewijzing aan een hash-segment. Het gebruikt de x
bediener de lijst één element vermenigvuldigen (1)
door de grootte van @elems
, zodat er een 1
voor elk van de sleutels in het schijfje aan de linkerkant:
@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;
De volgende toepassing van hashes maakt ook gebruik van het feit dat hashes en lijsten vaak door elkaar kunnen worden gebruikt om benoemde functie-args te implementeren:
sub hash_args {
my %args = @_;
my %defaults = (foo => 1, bar => 0);
my %overrides = (__unsafe => 0);
my %settings = (%defaults, %args, %overrides);
}
# This function can then be called like this:
hash_args(foo => 5, bar => 3); # (foo => 5, bar => 3, __unsafe ==> 0)
hash_args(); # (foo => 1, bar => 0, __unsafe ==> 0)
hash_args(__unsafe => 1) # (foo => 1, bar => 0, __unsafe ==> 0)
Bij gebruik als booleans zijn hashes waar als ze niet leeg zijn.
Scalaire referenties
Een referentie is een scalaire variabele (één voorafgegaan door $
) die naar andere gegevens verwijst.
my $value = "Hello";
my $reference = \$value;
print $value; # => Hello
print $reference; # => SCALAR(0x2683310)
Om de gegevens waarnaar wordt verwezen op te halen, moet u de verwijzing ongedaan maken.
say ${$reference}; # Explicit prefix syntax
say $$reference; # The braces can be left out (confusing)
Nieuwe postfix dereference syntax, standaard beschikbaar vanaf v5.24
use v5.24;
say $reference->$*; # New postfix notation
Deze "verwijzende waarde" kan vervolgens worden gewijzigd alsof het de oorspronkelijke variabele was.
${$reference} =~ s/Hello/World/;
print ${$reference}; # => World
print $value; # => World
Een verwijzing is altijd waarheidsgetrouw - zelfs als de waarde waarnaar deze verwijst vals is (zoals 0
of ""
).
Misschien wilt u een Scalaire referentie als:
U wilt een string aan een functie doorgeven en deze string voor u laten wijzigen zonder dat het een retourwaarde is.
U wilt expliciet voorkomen dat Perl de inhoud van een grote string op een bepaald moment in uw functie doorgeeft (vooral relevant voor oudere Perls zonder copy-on-write-reeksen)
U wilt tekenreeksachtige waarden met een specifieke betekenis ondubbelzinnig maken, van tekenreeksen die inhoud overbrengen, bijvoorbeeld:
- Ondubbelzinnig een bestandsnaam uit bestandsinhoud
- Maak geretourneerde inhoud van een geretourneerde foutreeks ondubbelzinnig
U wilt een lichtgewicht binnenstebuiten objectmodel implementeren, waarbij objecten die worden overhandigd aan de aanroepcode geen zichtbare metagegevens van de gebruiker bevatten:
our %objects; my $next_id = 0; sub new { my $object_id = $next_id++; $objects{ $object_id } = { ... }; # Assign data for object my $ref = \$object_id; return bless( $ref, "MyClass" ); }
Matrixreferenties
Arrayverwijzingen zijn scalars ( $
) die verwijzen naar Arrays.
my @array = ("Hello"); # Creating array, assigning value from a list
my $array_reference = \@array;
Deze kunnen als volgt korter worden gemaakt:
my $other_array_reference = ["Hello"];
Voor het wijzigen / gebruiken van arrayreferenties moet eerst worden verwijderd.
my @contents = @{ $array_reference }; # Prefix notation
my @contents = @$array_reference; # Braces can be left out
Nieuwe postfix dereference syntax, standaard beschikbaar vanaf v5.24
use v5.24;
my @contents = $array_reference->@*; # New postfix notation
Bij toegang tot de inhoud van een arrayref via index kunt u de ->
syntactische suiker gebruiken.
my @array = qw(one two three); my $arrayref = [ qw(one two three) ]
my $one = $array[0]; my $one = $arrayref->[0];
In tegenstelling tot arrays kunnen arrayrefs worden genest:
my @array = ( (1, 0), (0, 1) ) # ONE array of FOUR elements: (1, 0, 0, 1)
my @matrix = ( [1, 0], [0, 1] ) # an array of two arrayrefs
my $matrix = [ [0, 1], [1, 0] ] # an arrayref of arrayrefs
# There is no namespace conflict between scalars, arrays and hashes
# so @matrix and $matrix _both_ exist at this point and hold different values.
my @diagonal_1 = ($matrix[0]->[1], $matrix[1]->[0]) # uses @matrix
my @diagonal_2 = ($matrix->[0]->[1], $matrix->[1]->[0]) # uses $matrix
# Since chained []- and {}-access can only happen on references, you can
# omit some of those arrows.
my $corner_1 = $matrix[0][1]; # uses @matrix;
my $corner_2 = $matrix->[0][1]; # uses $matrix;
Bij gebruik als Boolean zijn verwijzingen altijd waar.
Hash-referenties
Hash-verwijzingen zijn scalaren die een aanwijzer naar de geheugenlocatie bevatten die de gegevens van een hash bevat. Omdat de scalaire waarde rechtstreeks naar de hash zelf verwijst, zijn wijzigingen die in de hash worden aangebracht niet lokaal, zoals bij een gewone hash, wanneer deze wordt doorgegeven aan een subroutine, maar in plaats daarvan globaal.
Laten we eerst eens kijken wat er gebeurt als je een normale hash doorgeeft aan een subroutine en deze daarbinnen wijzigt:
use strict;
use warnings;
use Data::Dumper;
sub modify
{
my %hash = @_;
$hash{new_value} = 2;
print Dumper("Within the subroutine");
print Dumper(\%hash);
return;
}
my %example_hash = (
old_value => 1,
);
modify(%example_hash);
print Dumper("After exiting the subroutine");
print Dumper(\%example_hash);
Wat resulteert in:
$VAR1 = 'Within the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
'old_value' => 1
};
Merk op dat nadat we de subroutine verlaten, de hash ongewijzigd blijft; alle wijzigingen daarin waren lokaal voor de subroutine wijzigen, omdat we een kopie van de hash hebben doorgegeven, niet de hash zelf.
Ter vergelijking: wanneer u een hashref doorgeeft, geeft u het adres door aan de oorspronkelijke hash, zodat wijzigingen in de subroutine worden aangebracht in de oorspronkelijke hash:
use strict;
use warnings;
use Data::Dumper;
sub modify
{
my $hashref = shift;
# De-reference the hash to add a new value
$hashref->{new_value} = 2;
print Dumper("Within the subroutine");
print Dumper($hashref);
return;
}
# Create a hashref
my $example_ref = {
old_value => 1,
};
# Pass a hashref to a subroutine
modify($example_ref);
print Dumper("After exiting the subroutine");
print Dumper($example_ref);
Dit zal resulteren in:
$VAR1 = 'Within the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
Typeglobs, typeglob refs, filehandles en constanten
Een typeglob *foo
bevat verwijzingen naar de inhoud van globale variabelen met die naam: $foo
, @foo
, $foo
, &foo
, enz. Je kunt er toegang toe krijgen als een hash en toewijzen om de symbolentabellen direct te manipuleren (kwaadaardig!).
use v5.10; # necessary for say
our $foo = "foo";
our $bar;
say ref *foo{SCALAR}; # SCALAR
say ${ *foo{SCALAR} }; # bar
*bar = *foo;
say $bar; # bar
$bar = 'egg';
say $foo; # egg
Typeglobs worden vaker gebruikt bij het omgaan met bestanden. open
produceert bijvoorbeeld een verwijzing naar een typeglob wanneer gevraagd wordt om een niet-globale filehandle te maken:
use v5.10; # necessary for say
open(my $log, '> utf-8', '/tmp/log') or die $!; # open for writing with encoding
say $log 'Log opened';
# You can dereference this globref, but it's not very useful.
say ref $log; # GLOB
say (*{$log}->{IO} // 'undef'); # undef
close $log or die $!;
Typeglobs kunnen ook worden gebruikt om globale alleen-lezen variabelen te maken, hoewel use constant
in breder gebruik is.
# Global constant creation
*TRUE = \('1');
our $TRUE;
say $TRUE; # 1
$TRUE = ''; # dies, "Modification of a read-only value attempted"
# use constant instead defines a parameterless function, therefore it's not global,
# can be used without sigils, can be imported, but does not interpolate easily.
use constant (FALSE => 0);
say FALSE; # 0
say &FALSE; # 0
say "${\FALSE}"; # 0 (ugh)
say *FALSE{CODE}; # CODE(0xMA1DBABE)
# Of course, neither is truly constant when you can manipulate the symbol table...
*TRUE = \('');
use constant (EVIL => 1);
*FALSE = *EVIL;
sigils
Perl heeft een aantal kenmerken:
$scalar = 1; # individual value
@array = ( 1, 2, 3, 4, 5 ); # sequence of values
%hash = ('it', 'ciao', 'en', 'hello', 'fr', 'salut'); # unordered key-value pairs
&function('arguments'); # subroutine
*typeglob; # symbol table entry
Deze zien eruit als tekens, maar zijn niet:
\@array; # \ returns the reference of what's on the right (so, a reference to @array)
$#array; # this is the index of the last element of @array
Je kunt na de sigil een beugel gebruiken als je daar zin in hebt. Af en toe verbetert dit de leesbaarheid.
say ${value} = 5;
Hoewel u verschillende tekens gebruikt om variabelen van verschillende typen te definiëren, is dezelfde variabele op verschillende manieren toegankelijk op basis van de tekens die u gebruikt.
%hash; # we use % because we are looking at an entire hash
$hash{it}; # we want a single value, however, that's singular, so we use $
$array[0]; # likewise for an array. notice the change in brackets.
@array[0,3]; # we want multiple values of an array, so we instead use @
@hash{'it','en'}; # similarly for hashes (this gives the values: 'ciao', 'hello')
%hash{'it','fr'}; # we want an hash with just some of the keys, so we use %
# (this gives key-value pairs: 'it', 'ciao', 'fr', 'salut')
Dit geldt vooral voor referenties. Om een waarde waarnaar wordt verwezen te gebruiken, kunt u tekens combineren.
my @array = 1..5; # This is an array
my $reference_to_an_array = \@array; # A reference to an array is a singular value
push @array, 6; # push expects an array
push @$reference_to_an_array, 7; # the @ sigil means what's on the right is an array
# and what's on the right is $reference_to_an_array
# hence: first a @, then a $
Hier is een misschien minder verwarrende manier om erover na te denken. Zoals we eerder zagen, kun je accolades gebruiken om te verpakken wat zich rechts van een teken bevindt. Je kunt dus @{}
als iets dat een matrixreferentie nodig heeft en je de gerefereerde matrix geeft.
# pop does not like array references
pop $reference_to_an_array; # ERROR in Perl 5.20+
# but if we use @{}, then...
pop @{ $reference_to_an_array }; # this works!
Het blijkt dat @{}
eigenlijk een uitdrukking accepteert:
my $values = undef;
say pop @{ $values }; # ERROR: can't use undef as an array reference
say pop @{ $values // [5] } # undef // [5] gives [5], so this prints 5
... en dezelfde truc werkt ook voor andere tekens.
# This is not an example of good Perl. It is merely a demonstration of this language feature
my $hashref = undef;
for my $key ( %{ $hashref // {} } ) {
"This doesn't crash";
}
... maar als het "argument" voor een teken eenvoudig is, kun je de accolades weglaten.
say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };
Dingen kunnen overdreven extravagant worden. Dit werkt, maar verantwoord alsjeblieft Perl.
my %hash = (it => 'ciao', en => 'hi', fr => 'salut');
my $reference = \%hash;
my $reference_to_a_reference = \$reference;
my $italian = $hash{it}; # Direct access
my @greets = @$reference{'it', 'en'}; # Dereference, then access as array
my %subhash = %$$reference_to_a_reference{'en', 'fr'} # Dereference ×2 then access as hash
Voor het meeste normale gebruik, kunt u gewoon subroutine namen gebruiken zonder een teken. (Variabelen zonder een sigil worden meestal "barewords" genoemd.) De &
sigil is alleen nuttig in een beperkt aantal gevallen.
Verwijzen naar een subroutine:
sub many_bars { 'bar' x $_[0] } my $reference = \&many_bars; say $reference->(3); # barbarbar
Een functie aanroepen die het prototype negeert.
Gecombineerd met goto, als een enigszins rare functieaanroep waarbij het huidige oproepframe wordt vervangen door de beller. Denk aan de API-aanroep linux
exec()
, maar dan voor functies.