in reply to Re: Side Effects
in thread Side Effects

Actually, $g::TaskList is not used, named, or referred to in the entire module that the above code appears in (though it is global). (It is used by an upstream sub that calls down into this subroutine though, but wouldn't $_ at least be local to the subroutine?) Even if $_ somehow became an alias to a global variable that was not used in the module in question, how would using $_ as an r-value undef said global?
$Body .= $_;
How does that undef $_, or anything it might be aliasing to? Sorry if I'm not getting it (I understand the idea that making it local will fix it, but I'd like to understand what makes this not work in the first place, because I just cannot figure out how $_ became an alias to TaskList). Thanks for the continued attention. :)

Replies are listed 'Best First'.
Re^3: Side Effects
by ikegami (Patriarch) on Apr 07, 2005 at 19:57 UTC
    It doesn't, it's the while(<LOG>) that clears it. while(<LOG>) is short for while ($_ = <LOG>). When the end of the file is reached, <LOG> returns undef, undefining $_. My snippets demonstrate this behaviour.
Re^3: Side Effects
by goodgulf (Initiate) on Apr 07, 2005 at 20:18 UTC
    OK, here's what I'm thinking.
    $Body .= $_ while <LOG>;
    is equivalent to
    while ($_ = <LOG>) { $Body .= $_; }
    Therefore, $_ is both an L-value and an R-value. If we assume for a moment that $_ is somehow an alias for $g::TaskList, then it should be correct that for each iteration of the while loop, $_ (and thus $g::TaskList) will get assigned the next line from <LOG>. At the end of the while loop, what would happen to $_? Would it get undef'd? Would this undef any aliases? So, let's assume all this is true... Here is my code path:
    In Localize.pm: (SNIP) foreach my $lang (@g::LanguageList) { $g::Language = $lang; unless (isExcludedBuild($g::Product, $g::Architecture, $g::Flavor) + || $g::Architecture =~ /ia64/i || $g::Language =~ /usa/i) { (SNIP) &BuildBlah(); } } (SNIP) In Utilities.pm: sub BuildBlah { my $FlavorVariation = shift; (snip) if(FileExists("Blah")) { SendMail($g::MailPurpose{"BuildFailed"}, "Blah", $FlavorVariat +ion); } (snip) } In Reporting.pm: sub SendMail { my $Purpose = shift; my @OptionalParameters = @_; my $Body = ""; (snip) $Body = "<html> <body background=nothing bgproperties=\"fixed\">"; if($Purpose eq $g::MailPurpose{BuildNominated}) { (snip) } elsif($Purpose eq $g::MailPurpose{BuildFailed}) { (snip) open(LOG, "$LogDir\\$g::BuildErrFile"); while (my $line = <LOG>) { $Body .= "${line}<br>"; } close LOG; }
    Although I've snipped a lot of code, this follows the execution path, and you can see that $g::TaskList is never mentioned going way way back up through several loops, modules and subroutine calls. Do I need to backtrack further? I would think the foreach above would wipe out any alias of $_ to TaskList that might have been set higher up in the stack trace.