Perl Language
Zmienne
Szukaj…
Składnia
- moja # deklaracja leksykalna
- nasza # globalna deklaracja
- $ foo # Skalar
- @foo # Array
- $ # foo # Array Last-Index
- % foo # Hash
- $ {$ foo} # Odwołanie do skalara
- @ {$ foo} # Odwołanie do tablicy
- $ # {$ foo} # Array-DeRef Last-Index
- % {$ foo} # Odwołanie skrótu
- $ foo [$ index] # Tablica zostanie zindeksowana
- $ {$ foo} [$ index] # Odwołanie do tablicy i uzyskaj indeks.
- $ foo -> [$ index] # Odwołanie do macierzy i zindeksowanie (uproszczone)
- $ foo {$ key} # Hash uzyskać wartość klucza
- $ {$ foo} {$ key} # Dereferencja mieszania i uzyskaj wartość klucza
- $ foo -> {$ key} # Dereferencja mieszania i uzyskaj wartość dla klucza (uproszczony)
- \ $ x # Odniesienie do skalara
- \ @x # Odniesienie do tablicy
- \% x # Odniesienie do skrótu
- = [] # Odwołanie do tablicy anonimowej (wbudowany)
- = {} # Odniesienie do anonimowego skrótu (wbudowany)
Skalary
Skalary są najbardziej podstawowym typem danych Perla. Są one oznaczone znakiem sigil $
i zawierają jedną wartość jednego z trzech typów:
- liczba (
3
,42
,3.141
itd.) - ciąg (
'hi'
,"abc"
itp.) - odwołanie do zmiennej (patrz inne przykłady).
my $integer = 3; # number
my $string = "Hello World"; # string
my $reference = \$string; # reference to $string
Perl konwertuje w locie liczby i ciągi , w oparciu o oczekiwania konkretnego operatora.
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
Podczas konwertowania łańcucha na liczbę Perl pobiera tyle cyfr z przodu łańcucha, ile może - dlatego dlaczego 20 apples
jest konwertowanych na 20
w ostatnim wierszu.
W zależności od tego, czy chcesz traktować zawartość skalara jako ciąg, czy liczbę, musisz użyć różnych operatorów. Nie mieszaj ich.
# 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;
Próba użycia operacji na ciągach liczbowych nie wywoła ostrzeżeń; próba użycia operacji liczbowych na ciągach nienumerycznych będzie. Należy pamiętać, że niektóre ciągi inne niż cyfry, takie jak 'inf'
, 'nan'
, '0 but true'
liczone jako liczby.
Tablice
Tablice przechowują uporządkowaną sekwencję wartości. Możesz uzyskać dostęp do zawartości według indeksu lub iterować nad nimi. Wartości pozostaną w kolejności, w której je wypełniłeś.
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
Tablice można modyfikować:
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')
Na koniec możesz zapętlić zawartość tablicy:
use v5.10; # necessary for 'say'
for my $number (@numbers_to_ten) {
say $number ** 2;
}
Gdy są używane jako booleany, tablice są prawdziwe, jeśli nie są puste.
Hashes
Skróty można rozumieć jako tabele przeglądowe. Możesz uzyskać dostęp do jego zawartości, określając klucz dla każdego z nich. Klucze muszą być ciągami znaków. Jeśli nie są, zostaną przekonwertowane na ciągi.
Jeśli podasz skrót po prostu znany klucz, będzie on służył jego wartości.
# 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');
W poniższym przykładzie zwróć uwagę na nawiasy klamrowe i pieczęć: uzyskujesz dostęp do elementu %hash
za pomocą $hash{key}
ponieważ $hash{key}
wartością jest skalar. Niektórzy uważają za dobrą praktykę cytowanie klucza, podczas gdy inni uważają ten styl za hałaśliwy. Cytowanie jest wymagane tylko w przypadku kluczy, które można pomylić z wyrażeniami takimi jak $hash{'some-key'}
my $greeting = $translations_of_hello{'spanish'};
Podczas gdy Perl domyślnie będzie próbował używać słów kluczowych jako ciągów, można również użyć modyfikatora +
, aby wskazać Perlowi, że klucz nie powinien być interpolowany, ale wykonany z wynikiem użycia jako klucza:
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};
Podobnie jak w przypadku tablic, możesz uzyskać dostęp do wielu elementów skrótu jednocześnie. Nazywa się to plasterkiem skrótu . Wynikową wartością jest lista, więc użyj @
sigil:
my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')
Iteracja po kluczach skrótu za keys
keys
zwróci elementy w losowej kolejności. Połącz z sort
jeśli chcesz.
for my $lang (sort keys %translations_of_hello) {
say $translations_of_hello{$lang};
}
Jeśli tak naprawdę nie potrzebujesz kluczy jak w poprzednim przykładzie, values
zwracają values
skrótu bezpośrednio:
for my $translation (values %translations_of_hello) {
say $translation;
}
Możesz również użyć pętli while z each
aby wykonać iterację po haszu. W ten sposób otrzymasz jednocześnie klucz i wartość, bez oddzielnego wyszukiwania wartości. Jego stosowanie jest jednak odradzane, ponieważ each
może złamać się w błędny sposób.
# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
say $translation;
}
Dostęp do nieuzbrojonych elementów zwraca undef, a nie błąd:
my $italian = $translations_of_hello{'italian'}; # undef
spłaszczania map
i list można używać do tworzenia skrótów z tablic. Jest to popularny sposób na utworzenie „zestawu” wartości, np. @elems
sprawdzenie, czy wartość jest w @elems
. Ta operacja zwykle zajmuje czas O (n) (tj. Proporcjonalny do liczby elementów), ale można ją wykonać w stałym czasie (O (1)), zamieniając listę w skrót:
@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
To wymaga wyjaśnienia. Zawartość @elems
zostaje @elems
do listy, która jest przetwarzana przez map
. map
akceptuje blok kodu, który jest wywoływany dla każdej wartości listy wejściowej; wartość elementu jest dostępna do użycia w $_
. Nasz blok kodu zwraca dwa elementy listy dla każdego elementu wejściowego: $_
, element wejściowy i 1
, tylko pewną wartość. Po uwzględnieniu spłaszczenia listy wynikiem jest to, że map { $_ => 1 } @elems
zmienia qw(xyxzt)
w (x => 1, y => 1, x => 1, z => 1, t => 1)
.
Gdy elementy te są przypisywane do skrótu, nieparzyste elementy stają się kluczami skrótu, a nawet elementy stają się wartościami skrótu. Gdy klucz zostanie określony wiele razy na liście, która ma zostać przypisana do skrótu, ostatnia wartość wygrywa. To skutecznie usuwa duplikaty.
Szybszy sposób na przekształcenie listy w skrót służy do przypisania do skrótu. Używa operatora x
do pomnożenia listy pojedynczych elementów (1)
przez rozmiar @elems
, więc dla każdego z klawiszy w wycinku po lewej stronie jest 1
wartość:
@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;
Następujące zastosowanie skrótów wykorzystuje również fakt, że skróty i listy mogą być często używane zamiennie do implementacji nazwanych argumentów funkcji:
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)
Gdy używane jako booleany, skróty są prawdziwe, jeśli nie są puste.
Skalarne odniesienia
Odwołanie jest zmienną skalarną (przedrostek $
), która „odnosi się” do niektórych innych danych.
my $value = "Hello";
my $reference = \$value;
print $value; # => Hello
print $reference; # => SCALAR(0x2683310)
Aby uzyskać dane, do których się odwołujesz , odznacz je.
say ${$reference}; # Explicit prefix syntax
say $$reference; # The braces can be left out (confusing)
Nowa składnia dereferencji po poprawce, domyślnie dostępna od wersji 5.24
use v5.24;
say $reference->$*; # New postfix notation
Tę „usuniętą wartość odniesienia” można następnie zmienić tak, jakby była to zmienna oryginalna.
${$reference} =~ s/Hello/World/;
print ${$reference}; # => World
print $value; # => World
Odwołanie jest zawsze prawdziwe - nawet jeśli wartość, do której się odnosi, to fałsz (np. 0
lub ""
).
Możesz chcieć odniesienia skalarnego, jeśli:
Chcesz przekazać ciąg do funkcji i zmodyfikować go, aby nie był wartością zwracaną.
Chcesz jawnie unikać Perla w sposób dorozumiany kopiowania zawartości dużego łańcucha w pewnym momencie przekazywania funkcji (szczególnie istotne na starszych Perlach bez ciągów kopiowania przy zapisie)
Chcesz ujednoznacznić wartości ciągów o określonym znaczeniu z ciągów przekazujących treść, na przykład:
- Ujednoznacznij nazwę pliku z treści pliku
- Ujednoznacznij zwróconą treść ze zwróconego ciągu błędów
Chcesz zaimplementować lekki model obiektu out out, w którym obiekty przekazywane do kodu wywołującego nie przenoszą widocznych dla użytkownika metadanych:
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" ); }
Referencje tablic
Odwołania do tablic to skalary ( $
), które odnoszą się do tablic.
my @array = ("Hello"); # Creating array, assigning value from a list
my $array_reference = \@array;
Można je utworzyć w skrócie w następujący sposób:
my $other_array_reference = ["Hello"];
Modyfikowanie / używanie odwołań do tablic wymaga uprzedniego ich usunięcia.
my @contents = @{ $array_reference }; # Prefix notation
my @contents = @$array_reference; # Braces can be left out
Nowa składnia dereferencji po poprawce, domyślnie dostępna od wersji 5.24
use v5.24;
my @contents = $array_reference->@*; # New postfix notation
Uzyskując dostęp do zawartości tablicy za pomocą indeksu, możesz użyć ->
cukru syntaktycznego.
my @array = qw(one two three); my $arrayref = [ qw(one two three) ]
my $one = $array[0]; my $one = $arrayref->[0];
W przeciwieństwie do tablic, odnośniki tablicowe można zagnieżdżać:
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;
Gdy są używane jako logiczne, odwołania są zawsze prawdziwe.
Referencje mieszania
Odwołania do skrótu to skalary, które zawierają wskaźnik do lokalizacji pamięci zawierającej dane skrótu. Ponieważ skalar wskazuje bezpośrednio na sam skrót, gdy jest on przekazywany do podprogramu, zmiany wprowadzone w haszu nie są lokalne dla podprogramu, jak w przypadku zwykłego skrótu, ale są globalne.
Najpierw sprawdźmy, co się stanie, gdy przekażesz normalny skrót do podprogramu i zmodyfikujesz go w nim:
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);
Co skutkuje w:
$VAR1 = 'Within the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
'old_value' => 1
};
Zauważ, że po wyjściu z podprogramu skrót pozostaje niezmieniony; wszystkie zmiany były lokalne dla podprogramu modyfikacji, ponieważ przekazaliśmy kopię skrótu, a nie samego skrótu.
Dla porównania, gdy przekazujesz skrót, przekazujesz adres do oryginalnego skrótu, więc wszelkie zmiany dokonane w ramach podprogramu zostaną wprowadzone w pierwotnym skrócie:
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);
Spowoduje to:
$VAR1 = 'Within the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
Typeglobs, referencje typeglob, uchwyty plików i stałe
Typeglob *foo
zawiera odwołania do zawartości zmiennych globalnych o tej nazwie: $foo
, @foo
, $foo
, &foo
itp. Możesz uzyskać do niego dostęp jak skrót i przypisać do bezpośredniego manipulowania tabelami symboli (zło!).
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
Typegloby są częściej obsługiwane w przypadku plików. na przykład open
tworzy odniesienie do kieliszka, gdy zostanie poproszony o utworzenie nieglobalnego uchwytu pliku:
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 $!;
Typegloby mogą być również używane do tworzenia globalnych zmiennych tylko do odczytu, chociaż use constant
jest w szerszym użyciu.
# 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 ma wiele pieczęci:
$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
Wyglądają jak pieczęcie, ale nie są:
\@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
Możesz użyć nawiasów klamrowych po pieczęci, jeśli powinieneś mieć takie skłonności. Czasami poprawia to czytelność.
say ${value} = 5;
Podczas gdy używasz różnych pieczęci do definiowania zmiennych różnych typów, do tej samej zmiennej można uzyskać dostęp na różne sposoby, w zależności od używanych pieczęci.
%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')
Dotyczy to szczególnie odniesień. Aby użyć wartości odniesienia, możesz łączyć sigile razem.
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 $
Oto być może mniej mylący sposób myślenia o tym. Jak widzieliśmy wcześniej, możesz użyć nawiasów klamrowych, aby owinąć to, co jest po prawej stronie pieczęci. Możesz więc pomyśleć o @{}
jako o czymś, co pobiera odwołanie do tablicy i daje ci odniesienie do tablicy.
# 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!
Jak się okazuje, @{}
akceptuje wyrażenie:
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
... i ta sama sztuczka działa również w przypadku innych pieczęci.
# 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";
}
... ale jeśli „spór” z pieczęcią jest prosty, możesz odejść od aparatu.
say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };
Rzeczy mogą stać się nadmiernie ekstrawaganckie. To działa, ale proszę odpowiedzialnie Perla.
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
W przypadku większości normalnych zastosowań można po prostu używać nazw podprogramów bez pieczęci. (Zmienne bez sigilu są zwykle nazywane „pustymi słowami”.) &
Sigil jest użyteczny tylko w ograniczonej liczbie przypadków.
Odwołanie do podprogramu:
sub many_bars { 'bar' x $_[0] } my $reference = \&many_bars; say $reference->(3); # barbarbar
Wywołanie funkcji ignorującej jej prototyp.
W połączeniu z goto, jako nieco dziwne wywołanie funkcji, które zastępuje bieżącą ramkę wywołania wywołaniem. Pomyśl o
exec()
API linuxexec()
, ale o funkcjach.