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

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
5.24.0

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 linux exec() , ale o funkcjach.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow