Бер*_*ров 8 perl autovivification
假设你有一个巨大的应用程序"开发";)由一个大团队.以下是当某人检查数据结构太深时可能发生的潜在灾难的简化模型.如果无法完全或在范围内禁用自动验证,如何解决此问题?非常感谢你 :) !!!!
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 );
Run Code Online (Sandbox Code Playgroud)
这输出如下:
$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
}
};
Run Code Online (Sandbox Code Playgroud)
是的,我知道有警告,但......可能为时已晚.
嘿伙计们,我的hashref引用一个绑定的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 '.$/;
}
Run Code Online (Sandbox Code Playgroud)
我所取得的是只触摸应用程序中的一个位置.现在所有像if($ some_ref - > {deep} {doot})的地方都会导致堆栈跟踪死亡.所以我很容易找到它们并纠正它们.这种新的着作是不可能的.Perl也适用于大型应用,你只需要知道更多;).
谢谢你们!我希望这对其他人也有帮助.
oeu*_*ete 21
相对较新的是autovivification
模块,它可以让你这样做:
no autovivification;
Run Code Online (Sandbox Code Playgroud)
非常直截了当.
zou*_*oul 15
您可能希望使用对象而不是哈希(请参阅Moose)或使用严格绑定哈希.或者你可以将警告变成错误,如果你真的想:
use warnings NONFATAL => 'all', FATAL => 'uninitialized';
Run Code Online (Sandbox Code Playgroud)
您可以使用Hash :: Util(核心模块)中的一个函数来锁定哈希.
use Hash::Util qw( lock_keys unlock_keys );
my $some_ref = { akey => { deeper => 1 } };
lock_keys %$some_ref;
print "too deep" if $some_ref->{deep}{shit} == 1;
Run Code Online (Sandbox Code Playgroud)
现在最后一个语句将抛出异常:
Attempt to access disallowed key 'deep' in a restricted hash
Run Code Online (Sandbox Code Playgroud)
当然,缺点是在检查散列中的密钥时必须非常小心以避免异常,即if exists ...
在访问密钥之前使用lof 来检查密钥.
如果您需要稍后再次向哈希添加密钥,则可以将其解锁:
unlock_keys %$some_ref;
$some_ref->{foo} = 'bar'; # no exception
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4660 次 |
最近记录: |