undef в Perl

undef в языке программирования Perl — это одно из значений, которое может содержаться в переменной. Если не присвоить переменной значение, то в переменной будет находится undef.

Вот пример Perl программы:

▶ Run
#!/usr/bin/perl

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

my $var;
print Dumper $var;

$var = 123;
print Dumper $var;

$var = undef;
print Dumper $var;

Эта программа выведет на экран:

$VAR1 = undef;
$VAR1 = 123;
$VAR1 = undef;

Сначала мы объявили переменную, но не присвоили ей никакого значения: my $var;. Дальше с помощью print Dumper $var; вывели информацию о значении этой переменной на экран (видно что в переменной содержится undef). После этого мы присвоили переменной число 123 и показали это на экране. А дальше с помощью кода $var = undef; мы присвоили переменной undef и опять вывели информацию об этом.

undef может быть элементом в массиве или значением в хеше:

▶ Run
#!/usr/bin/perl

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

my @arr = (1, undef, 'three');
print Dumper \@arr;

my %h = (
    a => undef,
);
print Dumper \%h;

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

Название undef происходит от английского слова undefined ("неопределено").

Чем undef не является

undef — это отдельное значение. Это не не строка 'undef', это не пустая строка '' и это не число 0. Все это — разные значения.

▶ Run
#!/usr/bin/perl

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

foreach my $var (undef, 'undef', '', 0) {
    print Dumper $var;
}

В случае хеша если значение ключа undef это не то же самое что в хеше отсутствует такой ключ.

Как проверить на undef

Для того чтобы проверить, является ли значение undef используется функция defined. Значение является undef если функция defined возвращает ложь:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

if (!defined($var)) {
    print 'var is undef';
}

Очень легко написать сабу is_undef, которая будет возвращать истину если в нее передали undef:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use feature qw(say);
use Data::Dumper;

sub is_undef {
    my ($maybe_undef) = @_;
    return !defined($maybe_undef);
}

my @arr = (1, undef, 'three');

foreach my $el (@arr) {
    say is_undef($el) ? 'undef' : 'not undef';
}

Но чаще всего так не делают, а используют функцию defined без какой-либо обвязки.

Существует еще один способ как можно проверить что в переменной содержится undef — это использовать оператор ~~ (этот оператор называется smartmatch). Этот оператор появился в Perl 5.10, но начиная с версии Perl 5.18 использование этого оператора выдает предупреждение Smartmatch is experimental at script.pl line 8.. Вот пример кода с этим оператором:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

if ($var ~~ undef) {
    print 'var is undef';
}

Чаще всего самый лучший способ для проверки на undef — это функция defined.

Perl undef и преобразование в JSON

Библиотеки для работы с JSON в Perl преобразуют Perl значение undef в null в JSON:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use JSON::PP;

print encode_json {
    a => undef,
};

Этот код выведет на экран {"a":null}.

И наоборот, при преобразовании из JSON null становится undef:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use JSON::PP;
use Data::Dumper;

print Dumper decode_json '[null]';

Этот код выведет на экран:

$VAR1 = [
          undef
        ];

Функция ref

Результат работы функции ref применительно к undef — это пустая строка ''. В этом плане undef не отличается от строк и чисел. Для undef, строк и чисел функция ref возвращает пустую строку:

▶ Run
#!/usr/bin/perl

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

foreach my $el ('asdf', undef, 100) {
    print Dumper ref($el);
}

Булево значение

При использовании undef в логических операциях undef — это ложь. Этот код выведет на экран текст false:

▶ Run
#!/usr/bin/perl

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

if (undef) {
    print 'true';
} else {
    print 'false';
}

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

В том случае если использовать undef в операциях со строками, то вместо undef будет использоваться пустая строка '', но также будет показано предупреждение.

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

print 'AAA' . $var . 'BBB';
▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

if ($var eq '') {
    print 'equal';
} else {
    print 'not equal';
}

В первом случае будет показано предупреждение Use of uninitialized value in concatenation (.) or string at script.pl line 10., во втором случае Use of uninitialized value in string eq at script.pl line 8..

Использование с числами

В том случае если использовать undef в операциях с числами, то вместо undef будет использовано число 0. но так же будет показано предупреждение.

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

print $var + 4;
▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

if ($var == 0) {
    print 'equal';
} else {
    print 'not equal';
}

В первом случае будет показано предупреждение Use of uninitialized value $var in addition (+) at script.pl line 8., во втором случае Use of uninitialized value $var in numeric eq (==) at script.pl line 8..

Интересно что при использовании оператора инкремента ++ предупреждения нет:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

my $var;

print $var++;

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

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

Комментарии