Perl:子例程 uneven/unusual 行为

Perl: Subroutine uneven/unusual behaviour

这是关于函数在 Perl 中的行为。

代码片段:

&mmg();
my $count;
sub mmg {
    &kkg();
    print "symlink at location updated with the value\n";
    $count++;
    print "$count is value of count \n";
} 



sub kkg {
    if (-d "/home/PPP/ee/dir1") {
        print "I got dir1\n";
        my @arr = glob ("/home/PPP/YEP");
        #..
        #..... Some more commands
        #..
        return;
    }
    else {
        sleep 5;
        &mmg();
    }
}

输出:

symlink at builds location updated with the value of link at builds location
1 is value of count 
symlink at builds location updated with the value of link at builds location
2 is value of count 
symlink at builds location updated with the value of link at builds location
3 is value of count 
symlink at builds location updated with the value of link at builds location
4 is value of count 
symlink at builds location updated with the value of link at builds location
5 is value of count 
symlink at builds location updated with the value of link at builds location
6 is value of count 

在这里,“dir1”不存在,我在 30-35 秒后创建。现在,据我了解,在 30-35 秒后(创建 dir1 时),只有 “构建位置的 symlink 更新为构建位置的 link 的值 \n 1 is value of count" 应该出现,即只有一次这些语句会被打印出来。但是,为什么这些被打印多次?

任何人都可以根据输出行为帮助我理解这个概念吗?我怎样才能让这个打印语句只打印一次?

我理解的概念:mmg() 将调用 kkg(),它会查看 dir1 是否存在。如果不是,则睡眠 5,然后再次调用 mmg()。 mmg() 将再次调用 kkg(),依此类推,直到出现 dir1。如果 dir1 可用,将返回 kkg(),而 mmg() 将继续执行并只打印一次内部内容。

这是您的代码的执行:

&mmg();
    &kkg();
        if ... 
        else mmg();
                 &kkg();
                     if ...
                     else mmg();
                              &kkg();
                                  if found! return to mmg()
                              print 1, sub finishes
                 print 2, sub finishes
    print 3, sub finishes

因为每次检查 dir1 是否存在时,都会启动一个新的 mmg() 进程,并且每个进程都会在完成之前打印一次。因为它们是相互嵌套的。

你应该做的是只使用 kkg() 作为布尔值,让 mmg() 处理循环控制,例如:

sub mmg {
    while (!kkg()) {
        sleep 5;      # do nothing
    }
    print "....";
    # done
}

sub kkg {
    if (-d "/home/PPP/ee/dir1") {
         # do stuff
         return 1;   # true
    }
    return 0;        # false
}

你甚至可能不需要 kkg()。

此外,您应该知道您使用的子调用方法 -- &NAME() -- 不是惯用的方法。在 perldoc perlsub 中,您可以阅读有关调用子例程的不同方式的信息:

NAME(LIST);    # & is optional with parentheses.
NAME LIST;     # Parentheses optional if predeclared/imported.
&NAME(LIST);   # Circumvent prototypes.
&NAME;         # Makes current @_ visible to called subroutine.

你应该使用 NAME().