Функция push() в Perl

В языке программирования Perl есть встроенная функция push(). С помощью этой функции можно добавлять элементы в конец Perl массива.

Вот пример:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my @arr = (1, 2);

push @arr, undef, 'Hello', 8;

print Dumper \@arr;

В этой программе определяется массив @arr с двумя элементами. Дальше с помощью функции push() в этом массив добавляют еще 3 элемента. undef, строка 'Hello' и число 8.

Результат работы этой программы:

$VAR1 = [
          1,
          2,
          undef,
          'Hello',
          8
        ];

Аргументы

push(@arr, $value1, $value2);
push(@arr, @other_arr);
push(@arr, @other_arr, @and_the_other_arr);

Стандартное использование функции push() — это передать в нее не менее двух элементов.

Первый элемент должен быть массив (в некоторых версиях Perl первый элемент еще может быть ссылкой на массив, но такое использование не рекомендуется, подробности в другом разделе ниже)

Следующие аргументы — это обычно скаляры или массивы. В массив из первого аргумента будут добавлены все элементы из следующих аргументов.

В качестве аргумента можно указать хеш push(@arr, %hash). В массив @arr будут добавлены все пары ключ-значение из хеша (тут есть особенность что порядок значений хеша неопределен и разные запуски одной и той же программы могут создавать элементы массива в разных последовательностях). Но в реальной жизни использование хеша в качестве аргумента функции push() встречается редко.

Если не указать ни одного аргумента, то будет ошибка:

Not enough arguments for push at script.pl line 3, near "push()"
Execution of script.pl aborted due to compilation errors.

Если указать один аргумент и этот аргумент массив push(@arr);, то ошибки не будет, это никак не изменит массив, но если в коде есть use warnings;, то будет предупреждение:

Useless use of push with no values at script.pl line 8.

Возвращаемое значение

Функция push() возвращает количество элементов которое стало в массиве после выполнения этой функции.

my $number = push(@arr, $value);

Этот код аналогичен вот такому коду:

push(@arr, $value);
my $number = scalar(@arr);

Возвращаемое значение push() нужно не очень часто. Очень часто используется push(@arr, $value), а возвращаемое значение игнорируется.

Использование ARRAYREF в качестве первого аргумента

Стандартное использование функции push() — первый аргумент это массив, в который добавляются элементы из всех остальных аргументов.

Но в языке программирования Perl был эксперимент. В том случае если первый аргумент это ссылка на массив, то функция push() сама делала разыменование этой ссылки и добавляла данные в массив.

Вот код.

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $arr = [];

push $arr, 1;

warn Dumper $arr;

Perl до версии 5.12 (включительно) на этот код выдает ошибку:

Type of arg 1 to push must be array (not private variable) at script.pl line 9, near "1;"
Execution of script.pl aborted due to compilation errors.

Начиная с версии Perl 5.14 и до версии 5.18 (включительно) это код добавлял элемент в ARRAYREF и результат был:

$VAR1 = [
          1
        ];

Perl 5.20 и 5.22 тоже добавлял элемент в ARRAYREF, но вместе с этим еще и выдавал предупреждение:

push on reference is experimental at script.pl line 9.
$VAR1 = [
          1
        ];

А начиная с версии 5.24 этого код уже выдает ошибку:

Experimental push on scalar is now forbidden at script.pl line 9, near "1;"
Execution of script.pl aborted due to compilation errors.

Этой фичей языка пользоваться не рекомендуется. Если вам нужно добавить элемент в ARRAYREF, то лучше всего написать явно push @{$arr}, 1; вместо push $arr, 1;

Вот код, который одинаково работает на всех версиях Perl:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $arr = [];

push @{$arr}, 1;

warn Dumper $arr;

Официальная документация

Вот вывод команды perldoc -f push:

       push ARRAY,LIST
       push EXPR,LIST
               Treats ARRAY as a stack by appending the values of LIST to the
               end of ARRAY.  The length of ARRAY increases by the length of
               LIST.  Has the same effect as

                   for $value (LIST) {
                       $ARRAY[++$#ARRAY] = $value;
                   }

               but is more efficient.  Returns the number of elements in the
               array following the completed "push".

               Starting with Perl 5.14, "push" can take a scalar EXPR, which
               must hold a reference to an unblessed array.  The argument will
               be dereferenced automatically.  This aspect of "push" is
               considered highly experimental.  The exact behaviour may change
               in a future version of Perl.

               To avoid confusing would-be users of your code who are running
               earlier versions of Perl with mysterious syntax errors, put
               this sort of thing at the top of your file to signal that your
               code will work only on Perls of a recent vintage:

                   use 5.014;  # so push/pop/etc work on scalars (experimental)

Связанные темы

Другие статьи

Комментарии