В чем разница между
if (defined $hash{$key}) { }
и
if (exists $hash{$key}) { }
Когда я знаю, что использовать?
Это хорошо документировано в записях perldoc для defined
и exists
. Вот краткое резюме:
defined $hash{key}
указывает, определено ли значение для данного ключа (т.е. не undef
). Используйте его для различения значений undefined и значений, которые являются ложными в булевом контексте, таких как 0
и ''
.
exists $hash{key}
указывает, содержит или нет %hash
данный ключ. Используйте его, чтобы различать значения undefined и несуществующие.
Это проще всего увидеть на примере. Учитывая этот хеш:
my %hash = (a => 1, b => 0, c => undef);
Вот результаты поиска, определения и существования:
# key value defined exists
a 1 1 1
b 0 1 1
c undef 0 1
d undef 0 0
На практике люди часто пишут только if ($hash{key}) {...}
, потому что (во многих распространенных случаях) только истинные значения являются значимыми/возможными. Если значения false действительны, вы должны добавить defined()
к тесту. exists()
используется гораздо реже. Наиболее распространенный случай, вероятно, при использовании хэша в качестве набора. например.
my %set = map { $_ => undef } 'a' .. 'z';
Использование undef
для заданных значений имеет несколько преимуществ:
undef
разделяют одно выделение (которое сохраняет память).exists()
тесты немного быстрее (потому что Perl не нужно извлекать значение, а только определить, что он есть).У него также есть недостаток, что вы должны использовать exists()
для проверки членства в наборе, что требует большего набора текста и сделает неправильную вещь, если вы забудете его.
Другое место, где exists
полезно, - это исследовать заблокированные хэши, прежде чем пытаться извлечь значение (которое вызовет исключение).
defined
проверяет значение переменной, exists
проверяет, была ли она ранее объявлена /инициализирована. Если он существует, простой и простой.
например:.
$hash{$key} = undef;
# various return values:
exists $hash{$key}; # true
defined $hash{$key}; # false
$hash{$key}; # false
$hash{$key} = 0;
# various return values:
exists $hash{$key}; # true
defined $hash{$key}; # true
$hash{$key}; # false
exists $hash{$foo}; # false
defined $hash{$foo}; #false
я полагаю?
my $var
существует и содержит значение undef
. my $var = 0
существует и содержит значение 0, поэтому определено.
Perl документация:
При использовании элемента хэша определяетсявы определяете ли значение, а не существует ли ключ в хеше. Используйте существует для последней цели.
Как указано в perldoc на exists
:
Учитывая выражение, которое указывает элемент хеша, возвращает true, если указанный элемент в хэше никогда не был инициализирован, даже если соответствующее значение undefined.
Элемент hash или array может быть истинным только в том случае, если он определен и определен только в том случае, если он существует, но обратное не обязательно выполняется.
То есть хэш может содержать элемент undefined, и если это так, то defined
-check вернет false
, тогда как exists
-check вернет true
.
Следовательно, вы должны использовать exists
, если хотите знать, существует ли данная запись в хэше, и defined
, если вы хотите знать, существует ли данная запись и которая определена.
exists
проверяет, содержит ли хеш заданный ключ, но не то, каково его значение, в то время как defined
просматривает значение данного ключа и определяет, определено ли оно или нет (и если ключ не существует, он возвращает undef
, так что работает, даже если ключа там нет.)
В этом примере показана разница. В общем, определенные работы для любой структуры и существуют связаны с хэшами.
my %hash=("1"=>undef);
print "exists:".exists($hash{"1"})."\n";
print "defined:".defined($hash{"1"})."\n";
Разница небольшая и не столь очевидная, поэтому ожидайте, что люди будут возиться с ней.
defined
также может быть использовано с другими типами переменных, в то время какexists
вызовет ошибку, если не используется с хешем или ключом массива (или подпрограммой).