Как отключить автовивификацию в Perl?
Предположим, у вас есть ОГРОМНОЕ приложение, «разработанное»;) большой командой. Вот упрощенная модель потенциальной катастрофы, которая может произойти, когда кто-то слишком глубоко проверяет структуру данных. Если невозможно полностью или автоматически отключить автовификацию, как обойти это? Большое спасибо :) !!!!
use strict; use warnings;use Data::Dumper;
my $some_ref = {akey=>{deeper=>1}};
print Dumper($some_ref );
if($some_ref->{deep}{doot} == 1){
print 'too deep '.$/;
}
if($some_ref->{deep}){
print 'Already in a deep doot'.$/;
}
print Dumper($some_ref );
Это выводит следующее:
$VAR1 = {
'akey' => {
'deeper' => 1
}
};
Use of uninitialized value in numeric eq (==) at autovivify_test.pl line 5.
Already in a deep doot
$VAR1 = {
'deep' => {},
'akey' => {
'deeper' => 1
}
};
Да, я знаю, что есть предупреждение, но ... может быть уже слишком поздно.
Эй, ребята, это может быть полезно сказать, что мой хэш-референс ссылается на связанный HASH.
Может быть, если я реализую хороший метод FETCH, который проверяет проверки глубже в структуре, я легко решу свою проблему?
я посмотрел наTie :: StrictHash,Tie :: Hash а такжеperltie, Вот упрощенная версия моего решения:
#!/usr/bin/env perl;
#test_tie.pl
package StrictHash;
use strict; use warnings;
use Tie::Hash;
our @ISA = qw(Tie::StdHash);
use Carp;
sub TIEHASH {
my $class = shift;
my $hash = bless {@_}, $class;
return $hash;
}
##========================================================================
## FETCH fails if applied to a member that doesn't exist.
##========================================================================
sub FETCH {
my ($hash, $key) = @_;
Carp::confess "key '$key' does not exist" unless exists $hash->{$key};
return $hash->{$key};
}
##========================================================================
package main;
use strict;use warnings;use Data::Dumper;
#Imagine StrictHash is in ./StrictHash.pm
#use StrictHash;
my %hash;
tie %hash, 'StrictHash', akey => {deeper=>1} ;
my $some_ref =\%hash;
print Dumper($some_ref );
if($some_ref->{deep}{doot} == 1){
print 'too deep '.$/;
}
Чего я достиг, так это прикоснулся только к одному месту в приложении. Теперь все места, такие как if ($ some_ref -> {deep} {doot}) будут вызывать die с помощью трассировки стека. Поэтому я легко их найду и исправлю. И новые сочинения такого рода НЕ будут возможны. Perl хорош и для больших приложений, вам просто нужно знать больше;).
Спасибо вам всем! Я надеюсь, что это помогает другим.