Is there an easy way for a perl program to know its nesting level?

时间:2018-02-03 08:35:48

标签: perl debugging

I am familiar with the caller function which can be used by a program to know where it was invoked, from which file, package etc. Is there an easy way for a program to know how deeply nested the caller was? The use case would be to add some debugging lines without having to explicitly count the nesting level.

I am not looking for a Stack Trace. I am trying to find how deeply nested a calling function is within the scope of another function.

For example:

sub my_debug {
    my ($txt) = @_;
    my ($package, $filename, $line) = caller;
    # Is there a way to know how deeply nested the caller is?
    my $level = ... # How to get this?
    print "DEBUG: You are calling from package $package in $filename "
        . "line $line nesting level $level: MSG: $txt\n";
}

sub badly_nested {
    for my $i ( 1..10 ) {
        # 1-level deep
        for my $j ( 1 .. 10 ) {
            # 2-levels deep
            my_debug( "j is $j" );
            for my $k ( 1 .. 10 ) {
                # 3-levels deep
            }
        }
    }
}

1 个答案:

答案 0 :(得分:4)

CPAN上提供的Perl模块,Scope :: Upper可以满足您的要求:

use strict;                     
use warnings;                   

use Scope::Upper qw(SCOPE);     

print SCOPE(), "\n";            
{                               
    print SCOPE(), "\n";        
    {                           
        print SCOPE(), "\n";    
        {                       
            print SCOPE(), "\n";
        }                       
        print SCOPE(), "\n";    
    }                           
    print SCOPE(), "\n";        
}                               
print SCOPE(), "\n";            

此代码的输出为:

0
1
2
3
2
1
0

因此,它可以让您查看当前作用域的深度,可用于推断嵌套循环的深度。您可以将偏移量传递给SCOPE()函数。因此,例如,如果您调用{SCOPE(1)},则返回值将为零,尽管深度为一个范围。如果您不关心自己是否在子程序或if块内,这可能非常有用,因此您需要更深入地计算。例如:

if ($foo) {
    foreach my $x (1..10) {
        foreach my $y (1..10) {
            print SCOPE(1), "\n";
        }
    }
}

在此示例中,响应将显示范围深度为2而不是3,因为将1传递给SCOPE()会提示它忽略if(){...}块的范围。