如何在Perl中禁用自动生存? [英] How do I disable autovivification in Perl?

查看:107
本文介绍了如何在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
                    }
        };

是的,我知道有警告,但是...可能为时已晚.

嘿,说我的hashref引用了绑定的HASH可能会有所帮助.

也许如果我实现了一种很好的FETCH方法,该方法可以在结构中进行更深入的检查,那么我可以轻松解决问题吗?


我查看了 Tie :: StrictHash Tie :: Hash

我实现的是仅触摸应用程序中的一个位置. 现在,所有类似if($ some_ref-> {deep} {doot})的地方都将导致堆栈跟踪死亡. 因此,我将轻松找到并纠正它们. 这样的新著作将是不可能的. Perl也适用于大型应用程序,您只需要了解更多;).

谢谢大家! 我希望这对其他人也有帮助.

解决方案

您可能想使用对象而不是哈希(请参见严格绑定哈希.或者,如果您确实愿意,也可以将警告变成错误:

use warnings NONFATAL => 'all', FATAL => 'uninitialized';

Suppose you have a HUGE application "develoopped" ;) by a big team. Here is a simplified model of the potential disaster that may occur when somebody checks too deep in a data structure. If not possible to disable autovification completely or in scope, how to work around this? Thank you very much :) !!!!

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 );

This outputs the following:

$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
                    }
        };

Yes I know there is a warning, but... it may be too late.

Hey guys it will may be help to say that my hashref references a tied HASH.

May be if I implement a good FETCH method which checks for checks deeper in the structure, I will solve easily my problem?


I looked at Tie::StrictHash,Tie::Hash and perltie. Here is simplified version of my solution:

#!/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 '.$/;
}

What I achieved is to touch only one place in the app. Now all Places like if($some_ref->{deep}{doot}) will cause die with stack-trace. So I will easily find them and correct them. And new writings of this kind will NOT be possible. Perl is good for big apps too, you just need to know more ;).

Thank you all! I hope this helps others too.

解决方案

You might want to use an object instead of the hash (see Moose) or use a strict tied hash. Or you can turn warnings into errors, if you really want to:

use warnings NONFATAL => 'all', FATAL => 'uninitialized';

这篇关于如何在Perl中禁用自动生存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆