Поиск…


Синтаксис

  • моя # Лексическая декларация
  • наша глобальная декларация #
  • $ foo # Скаляр
  • @foo # Массив
  • $ # foo # Массив Last-Index
  • % foo # Хеш
  • $ {$ foo} # Scalar De-Reference
  • @ {$ foo} # Array De-Reference
  • $ # {$ foo} # Array-DeRef Last-Index
  • % {$ foo} # Hash De-Reference
  • $ foo [$ index] # Массив индексируется
  • $ {$ foo} [$ index] # Array De-Reference и индексируется.
  • $ foo -> [$ index] # Array De-Reference и индексироваться (упрощено)
  • $ foo {$ key} # Хеш получить значение для ключа
  • $ {$ foo} {$ key} # Hash Dereference и получить значение для ключа
  • $ foo -> {$ key} # Hash Dereference и получить значение для ключа (упрощенного)
  • \ $ x # Ссылка на скаляр
  • \ @x # Ссылка на массив
  • \% x # Ссылка на хэш
  • = [] # Ссылка на анонимный массив (Inline)
  • = {} # Ссылка на анонимный хэш (Inline)

Скаляры

Скаляры - это самый базовый тип данных Perl. Они отмечены сигилой $ и содержат одно значение одного из трех типов:

  • число ( 3 , 42 , 3.141 и т. д.),
  • строка ( 'hi' , "abc" и т. д.)
  • ссылка на переменную (см. другие примеры).
my $integer = 3;                      # number
my $string = "Hello World";           # string
my $reference = \$string;             # reference to $string

Perl конвертирует между числами и строками «на лету» , исходя из того, что ожидает конкретный оператор.

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

При преобразовании строки в число Perl берет столько цифр от строки, сколько может, поэтому 20 apples преобразуются в 20 в последней строке.

Исходя из того, хотите ли вы обрабатывать содержимое скаляра в виде строки или числа, вам нужно использовать разные операторы. Не смешивайте их.

# 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;

Попытка использования строковых операций над номерами не вызывает предупреждений; попытка использовать числовые операции для нечисловых строк. Имейте в виду, что некоторые нецифровые строки, такие как 'inf' , 'nan' , '0 but true' считаются цифрами.

Массивы

Массивы хранят упорядоченную последовательность значений. Вы можете получить доступ к содержимому по индексу или перебрать их. Значения будут оставаться в том порядке, в котором вы их заполняли.

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    

Массивы изменяемы:

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

Наконец, вы можете перебрать содержимое массива:

use v5.10; # necessary for 'say'
for my $number (@numbers_to_ten) {
  say $number ** 2;
}

При использовании в качестве булевых элементов массивы являются истинными, если они не пусты.

Хэш

Хэши можно понимать как таблицы поиска. Вы можете получить доступ к его содержимому, указав ключ для каждого из них. Ключи должны быть строками. Если это не так, они будут преобразованы в строки.

Если вы дадите хэш просто известный ключ, он будет служить вам вашей ценности.

# 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'); 

В следующем примере обратите внимание на скобки и сигилы: вы получаете доступ к элементу %hash с помощью $hash{key} потому что значение, которое вы хотите, является скаляром. Некоторые считают хорошей практикой процитировать ключ, в то время как другие находят этот стиль визуально шумным. Цитирование требуется только для ключей, которые могут быть ошибочно приняты за выражения типа $hash{'some-key'}

my $greeting = $translations_of_hello{'spanish'};

В то время как Perl по умолчанию будет пытаться использовать просто слова как строки, + модификатор также может использоваться для указания Perl, что ключ не должен быть интерполирован, а выполнен с результатом выполнения, используемым в качестве ключа:

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};

Подобно массивам, вы можете одновременно получить доступ к нескольким элементам хэша. Это называется хэш-срезом . Результирующее значение - это список, поэтому используйте @ sigil:

my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')

Итерации по клавишам хэша с keys keys возвращают элементы в произвольном порядке. Совместимый с sort , если вы хотите.

for my $lang (sort keys %translations_of_hello) {
  say $translations_of_hello{$lang};
}

Если вам действительно не нужны такие ключи, как в предыдущем примере, values возвращают values хеша напрямую:

for my $translation (values %translations_of_hello) {
  say $translation;
}

Вы также можете использовать цикл while, each должен перебирать хэш. Таким образом, вы получите как ключ, так и значение в одно и то же время без отдельного поиска значений. Его использование, однако, обескураживает, так как each может нарушить путаницу.

# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
  say $translation;
}

Доступ к неустановленным элементам возвращает undef, а не ошибку:

my $italian = $translations_of_hello{'italian'}; # undef

map и list flattening можно использовать для создания хэшей из массивов. Это популярный способ создания «набора» значений, например, чтобы быстро проверить, находится ли значение в @elems . Эта операция обычно занимает время O (n) (т. Е. Пропорционально количеству элементов), но может выполняться в постоянное время (O (1)) путем превращения списка в хэш:

@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

Это требует некоторого объяснения. Содержимое @elems считывается в список, который обрабатывается map . map принимает блок кода, который вызывается для каждого значения его входного списка; значение элемента доступно для использования в $_ . Наш кодовый блок возвращает два элемента списка для каждого элемента ввода: $_ , входной элемент и 1 , только некоторое значение. Как только вы учитываете сглаживание списка, результатом является то, что map { $_ => 1 } @elems превращает qw(xyxzt) в (x => 1, y => 1, x => 1, z => 1, t => 1) .

Поскольку эти элементы назначаются в хеш, нечетные элементы становятся хеш-ключами, а даже элементы становятся хеш-значениями. Когда ключ указан несколько раз в списке, который должен быть присвоен хэшу, выигрывает последнее значение. Это эффективно отменяет дубликаты.

Более быстрый способ превратить список в хэш использует назначение хэш-фрагмента. Он использует оператор x чтобы умножить один элементный список (1) на размер @elems , поэтому для каждого из ключей в срезе с левой стороны есть 1 значение:

@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;

Следующее приложение хешей также использует тот факт, что хэши и списки часто могут быть взаимозаменяемы для реализации названных функций args:

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)

При использовании в качестве булевых хешей истинны, если они не пусты.

Скалярные ссылки

Ссылка - это скалярная переменная (одна префикс $ ), которая «ссылается» на некоторые другие данные.

my $value     = "Hello";
my $reference = \$value;
print $value;     # => Hello
print $reference; # => SCALAR(0x2683310)

Чтобы получить указанные данные, вы удалите ссылку на него.

say ${$reference};                  # Explicit prefix syntax
say $$reference;                    # The braces can be left out (confusing)
5.24.0

Новый синтаксис разыменования постфикса, доступный по умолчанию из v5.24

use v5.24;
say $reference->$*; # New postfix notation

Это «де-ссылочное значение» может быть затем изменено, как и исходная переменная.

${$reference} =~ s/Hello/World/;
print ${$reference};  # => World
print $value;         # => World

Ссылка всегда правдивая - даже если значение, на которое оно ссылается, является ложным (например, 0 или "" ).

Возможно, вам понадобится Scalar Reference If:

  • Вы хотите передать строку в функцию и изменить ее для этой строки, не возвращая ее.

  • Вы хотите явно запретить Perl неявно копировать содержимое большой строки в какой-то момент передачи вашей функции (что особенно важно для старых Perls без строк копирования на запись)

  • Вы хотите устранить неоднозначные значения строк с определенным значением из строк, передающих контент, например:

    • Disambiguate имя файла из содержимого файла
    • Disambiguate возвратил содержимое из строки возвращаемой ошибки
  • Вы хотите реализовать облегченную внутреннюю объектную модель, где объекты, переданные вызывающему коду, не имеют видимых пользователем метаданных:

    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" );
    }
    

Ссылки на массивы

Массивные ссылки - это скаляры ( $ ), которые относятся к массивам.

my @array = ("Hello"); # Creating array, assigning value from a list
my $array_reference = \@array;

Их можно создать более коротко:

my $other_array_reference = ["Hello"];

Изменение / использование ссылок на массивы требует разглашения их в первую очередь.

my @contents = @{ $array_reference };               # Prefix notation
my @contents = @$array_reference;                   # Braces can be left out
5.24.0

Новый синтаксис разыменования постфикса, доступный по умолчанию из v5.24

use v5.24;
my @contents = $array_reference->@*; # New postfix notation 

При доступе к содержимому arrayref по индексу вы можете использовать синтаксический сахар -> .

my @array = qw(one two three);      my $arrayref = [ qw(one two three) ]
my $one = $array[0];                my $one = $arrayref->[0];

В отличие от массивов, arrayrefs может быть вложенным:

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;  

При использовании в качестве булева ссылки всегда верны.

Хэш-ссылки

Хеш-ссылки - это скаляры, содержащие указатель на ячейку памяти, содержащую данные хэша. Поскольку скаляр указывает непосредственно на сам хэш, когда он передается подпрограмме, изменения, сделанные в хэше, не являются локальными для подпрограммы, как при регулярном хэше, но вместо этого являются глобальными.

Сначала давайте рассмотрим, что происходит, когда вы передаете обычный хеш подпрограмме и изменяете ее внутри:

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

Результат:

$VAR1 = 'Within the subroutine';
$VAR1 = {
          'new_value' => 2,
          'old_value' => 1
        };
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
          'old_value' => 1
        };

Обратите внимание, что после выхода из подпрограммы хэш остается неизменным; все изменения в нем были локальными для подпрограммы изменения, потому что мы передали копию хэша, а не самого хэша.

Для сравнения, когда вы передаете hashref, вы передаете адрес исходному хешу, поэтому любые изменения, сделанные в подпрограмме, будут сделаны в исходном хэше:

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

Это приведет к:

$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, дескрипторы файлов и константы

Типglob *foo содержит ссылки на содержимое глобальных переменных с таким именем: $foo , @foo , $foo , &foo и т. Д. Вы можете получить к нему доступ как хэш и назначить непосредственно манипулировать таблицами символов (зло!).

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 чаще обрабатываются при работе с файлами. open , например, создает ссылку на типglob, когда его просят создать неглобальный дескриптор файла:

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 также могут использоваться для создания глобальных переменных только для чтения, хотя use constant используется более широко.

# 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 имеет ряд сигил:

$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

Они выглядят как сигилы, но не являются:

\@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

Вы можете использовать фигурные скобки после сигилы, если вы так склонны. Иногда это улучшает читаемость.

say ${value} = 5;

Хотя вы используете разные сигилы для определения переменных разных типов, к одной и той же переменной можно обращаться по-разному в зависимости от того, какие символы вы используете.

%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')

Это особенно касается ссылок. Чтобы использовать ссылочное значение, вы можете комбинировать сигилы вместе.

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 $

Вот, возможно, менее запутанный способ подумать об этом. Как мы видели ранее, вы можете использовать фигурные скобки, чтобы обернуть то, что находится справа от сигилы. Поэтому вы можете думать о @{} как о чем-то, что берет ссылку на массив и дает вам ссылочный массив.

# 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!

Как оказалось, @{} фактически принимает выражение:

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

... и тот же трюк работает и для других сигил.

# 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";
}

... но если «аргумент» для сигилы прост, вы можете оставить фигурные скобки.

say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };

Все может стать чрезмерно экстравагантным. Это работает, но, пожалуйста, 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

Для большинства нормальных применений вы можете просто использовать имена подпрограмм без сигилы. (Переменные без сигилы обычно называются «barewords»). & Sigil полезен только в ограниченном числе случаев.

  • Составление ссылки на подпрограмму:

    sub many_bars { 'bar' x $_[0] }
    my $reference = \&many_bars;
    say $reference->(3); # barbarbar
    
  • Вызов функции, игнорирующей ее прототип.

  • В сочетании с goto, как немного странный вызов функции, у которого текущий кадр вызова заменен вызывающим. Подумайте о вызове API linux exec() , но для функций.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow