Можно ли безопасно получить доступ к данным во вложенной структуре данных, как это делает Template Toolkit? - PullRequest
2 голосов
/ 17 июня 2010

Существует ли модуль, который обеспечивает такую ​​же функциональность, как Template Toolkit при доступе к глубоко вложенной структуре данных?Я хочу извлечь что-то вроде $a = $hash{first}[0]{second}{third}[3] без необходимости тестировать каждую часть структуры, чтобы увидеть, соответствует ли она тому, что я ожидаю.Если %hash = {} я хочу $a = undef, не выдаст ошибку.

Ответы [ 4 ]

2 голосов
/ 17 июня 2010

Perl сделает именно то, что вы описали

Эта функция называется автовивификацией.Это означает, что контейнерные объекты появятся сразу после их использования.Это сохраняется до тех пор, пока вы не нарушите какой-либо прецедент, который вы установили сами.

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

Если вы также хотите защитить от неправильного использования, вы можете заключить вложенный поиск вeval block:

my $x = eval{ $hash{first}[0]{second}{third}[3] };

Это вернет undef, если eval не удастся.Обратите внимание, что это НЕ строка Eval, которая будет написана eval '....';.В блочной форме Perl eval аналогичен конструкции try {...} в других языках.

Чтобы определить, произошел ли сбой eval или действительно ли значение в этой позиции undef, проверьте, не является лиспециальная переменная $@ имеет значение true.Если это так, eval не удалось, и причина будет в $@.Было бы написано:

my $x = eval{ $hash{first}[0]{second}{third}[3] };

if (!$x and $@) { die "nested dereference failed: $@" }

Или вы можете использовать модуль Try :: Tiny , который абстрагирует детали реализации и защищает от нескольких крайних случаев:

use Try::Tiny;

my $x;
try {
    $x = $hash{first}[0]{second}{third}[3];
} catch {
    die "nested dereference failed: $_";
};
1 голос
/ 17 июня 2010

Извлечение Data :: Diver .

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

use strict;
use warnings;

use Data::Diver qw( Dive );

my $a = Dive( \%hash, 'first', 0, 'second', 'third', 3 );

if( defined $a ) {
    print "Got '$a'.\n";
}
else {
    print "Got no match.\n";
}
1 голос
/ 17 июня 2010

Вероятно, ваша ошибка связана с неверным уровнем косвенности, а не потому, что у вас нет значения.Обратите внимание, что ваша хеш-переменная является скалярной ссылкой на хеш, а не хеш.Поэтому он должен быть определен как $hash = {}, а не %hash = {}.Затем вы получаете доступ к элементам там как $ hash -> {first}, а не $ hash {first}.И так далее.Если вы правильно определите хеш и попробуете что-то вроде $hash->{first}->[0]->{second}->{third}->[3], вы получите ровно undef, как и хотели, без ошибок.

Примечание: всегда use strict!

0 голосов
/ 17 июня 2010

Как-то так?

use strict;
use warnings;

my %hash;
my $elem = _eval( '$hash{first}[0]{second}{third}[3]' );

sub _eval {return (eval shift) // undef}

Конечно, вы могли бы также сделать:

my $elem = eval {$hash{first}[0]{second}{third}[3] // undef};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...