Using a variable from outer scope in a sub called in foreach

戏子无情 提交于 2019-12-04 19:00:29

The foreach $oldfile (@files) does not assign values to the my $oldfile declared at the top. That one is a lexical variable, not global, and in such a case a new lexical $oldfile is created for the loop's scope. This is a particular property of foreach alone. See this post for details.

Since the $oldfile in foreach is a lexical in a dynamic scope it is invisible to the sub. But the sub sees my $oldfile declared for the static scope of the file. From Private Variables via my()

... lexical variables declared with my are totally hidden from the outside world, including any called subroutines. This is true if it's the same subroutine called from itself or elsewhere--every call gets its own copy.

This doesn't mean that a my variable declared in a statically enclosing lexical scope would be invisible. Only dynamic scopes are cut off. For example, ...

That $oldfile at the top, seen by the sub, stays as it was before the loop, uninitialized.

Altogether, a simple "fix" to get the expected behavior is to make $oldfile on top a global variable, so to replace my $oldfile with our $oldfile.  

However, why rely on global variables? Why not pass to functions what they need

foreach my $oldfile (@files) {
    ...
    if (...) {
        rename_file($dirname, $oldfile);
    ...
}

sub rename_file {
    my ($dirname, $oldfile) = @_;
    ...
}

You are nicely using strict already and declaring everything else. Then you don't need, and should not have, the file-wide lexical my $oldfile; declared on top.

When you declare a variable in a sub, it is shielded from variables with the same name outside the sub's scope. So here you know what $oldfile is – it is exactly what you passed to the function.

That way your sub also has a well defined interface and does not depend on arbitrary values in the surrounding code. This is crucial for clear delineation of scope and for modularity.

More generally, using a global variable while strict is in place and other things declared is like planting a mine for the maintenance programmer, or for yourself the proverbial six months later.

I suggest to also read Coping with Scoping by Mark-Jason Dominus.


I don't recommend this unless there is a very specific and solid reason for a global-like our variable.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!