[32341] in Perl-Users-Digest
Perl-Users Digest, Issue: 3608 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Wed Feb 8 09:09:26 2012
Date: Wed, 8 Feb 2012 06:09:08 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Wed, 8 Feb 2012 Volume: 11 Number: 3608
Today's topics:
Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? <peter@makholm.net>
Re: Lifetime of my variables? <ben@morrow.me.uk>
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? <peter@makholm.net>
Re: Lifetime of my variables? <rweikusat@mssgmbh.com>
Re: Lifetime of my variables? <ben@morrow.me.uk>
Re: Lifetime of my variables? <ben@morrow.me.uk>
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? <ben@morrow.me.uk>
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? (Seymour J.)
Re: Lifetime of my variables? <rweikusat@mssgmbh.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Tue, 07 Feb 2012 07:33:59 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Lifetime of my variables?
Message-Id: <4f311a37$1$fuzhry+tra$mr2ice@news.patriot.net>
I could find nothing in the Perl documentation on the lifetime of my
variables. The scope of the name is lexical, but what about the value?
Specifically, if a my variable is declared in a block, does it retain
its value from the previous time you entered the block? If a my
variable is declared in a while statement, does it retain its value
across iterations?
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Tue, 07 Feb 2012 14:56:46 +0100
From: Peter Makholm <peter@makholm.net>
Subject: Re: Lifetime of my variables?
Message-Id: <87lioeu4pt.fsf@vps1.hacking.dk>
Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
> I could find nothing in the Perl documentation on the lifetime of my
> variables. The scope of the name is lexical, but what about the value?
> Specifically, if a my variable is declared in a block, does it retain
> its value from the previous time you entered the block?
Basically you get a new variable each time you reach the my statement.
If you want to have a variable that keeps the vallue between each time
you enter the block, you should look at state variables. See the perlsub
manual page, the section titled "Persistent Private Variables".
//Makholm
------------------------------
Date: Tue, 7 Feb 2012 14:57:20 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Lifetime of my variables?
Message-Id: <gnq709-7ff2.ln1@anubis.morrow.me.uk>
Quoth Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>:
> I could find nothing in the Perl documentation on the lifetime of my
> variables. The scope of the name is lexical, but what about the value?
> Specifically, if a my variable is declared in a block, does it retain
> its value from the previous time you entered the block? If a my
> variable is declared in a while statement, does it retain its value
> across iterations?
No in both cases. If you take a reference and pass it outside the block
you can make the variable outlast the name, but next time you enter the
block the name will get a fresh (undefined) variable attached to it. (As
an optimisation, if the variable has no outstanding references at the
end of the block perl will clear it out and reuse the same memory next
time the block is entered, but this only applies in situations where it
cannot make any difference to the semantics.)
For example
use 5.010;
my $y;
for (1..3) {
say "ITERATION: $_";
my $x;
say "New lexical: [$x] " . \$x;
$x = $_;
say "After assignment: [$x]";
$_ == 2 and $y = \$x;
}
say "Captured lexical: [$$y] $y";
gives
ITERATION: 1
New lexical: [] SCALAR(0x822608)
After assignment: [1]
ITERATION: 2
New lexical: [] SCALAR(0x822608)
After assignment: [2]
ITERATION: 3
New lexical: [] SCALAR(0x8195d8)
After assignment: [3]
Captured lexical: [2] SCALAR(0x822608)
so the second iteration reused the same memory as the first, but cleared
it out so it looked like a fresh variable, whereas the third had to
allocate a new variable since the old one was still referenced by $y. In
both cases the variable started the loop containing undef.
If you want the behaviour you describe, you can get it from perl 5.10
with 'state' variables. A 'state' variable is a lexical just like 'my',
but there is only ever one instance of it which is shared by all entries
into that block. Any initialisation is performed exactly once, the first
time that statement is executed. (This is nearly exactly like static
variables in C, if you know C.)
Since 'state' was a new keyword in 5.10, it must be enabled (just like
'say') with the 'feature' pragma. The simplest way to do this is to say
use 5.010;
which implicitly performs
use feature ":5.10";
which is equivalent to
use feature qw/switch state say/;
It currently isn't possible to initialise an array or hash state
variable; I can't remember why, but there was a nearly good reason :).
Assigning a ref to a scalar state variable works perfectly well, so
that's the obvious workaround.
Ben
------------------------------
Date: Tue, 07 Feb 2012 13:20:32 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f316b70$2$fuzhry+tra$mr2ice@news.patriot.net>
In <gnq709-7ff2.ln1@anubis.morrow.me.uk>, on 02/07/2012
at 02:57 PM, Ben Morrow <ben@morrow.me.uk> said:
>No in both cases. If you take a reference and pass it outside the
>block you can make the variable outlast the name, but next time you
>enter the block the name will get a fresh (undefined) variable
>attached to it.
That's the behavior I wanted, but somehow it's getting the value from
the previous iteration. I'd post the full code, but it's 1723 lines
long.
>If you want the behaviour you describe,
Superficially it looks as though I'm getting that behavior, and I'm
trying to figure out why :-(
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Tue, 07 Feb 2012 13:14:14 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f3169f6$1$fuzhry+tra$mr2ice@news.patriot.net>
In <87lioeu4pt.fsf@vps1.hacking.dk>, on 02/07/2012
at 02:56 PM, Peter Makholm <peter@makholm.net> said:
>If you want to have a variable that keeps the vallue between each
>time you enter the block, you should look at state variables.
I've got the opposite problem; I've got a variable that is supposed to
be undefrined at the beginning of each iteration and it's picking up a
value from a previous iteration. The program is rather large, but the
basic structure is
my $filer = $parser->filer;
...
mailfile: while (my $mailfile=shift) {
print STDOUT "\nunobfuscate.cmd processing file $mailfile\n";
my $entity = $parser->parse_open("$mailfile")
or die "$mailfile parse failed\n";
...
my $prevHELO;
...
print STDERR "\n\$prevHELO=$prevHELO\n";
...
}
foreach (@Received[$ReceivedIx..$#Received]) {
...
doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
$+{BY1}, $+{BY2} // '') || last;
...
sub doReceived {
...
if ($prevHELO) {
msg("\t\$prevHELO=$prevHELO\n");
msg("\t\$prevSrc=$prevSrc\n");
unless (uc $by1 eq $prevHELO or
"\U$by2.$by1" eq $prevHELO or
uc $by1 eq $prevSrc or
"\U$by2.$by1" eq $prevSrc) {
$prevHELO=$HELO;
msg("\t\$prevHELO after mismatch set to $prevHELO\n");
return undef();
}
if ($prevBogus) {
msg("\tPrevious Received field was bad; skipping $From\n");
return undef();
}
} elsif ($lookup && $MARF) {
$host_info{$IP}{MARF}=1 if $IP;
$host_info{$rDNS}{MARF}=1 if $rDNS;
}
$prevHELO=$HELO;
msg("\t\$prevHELO set to $prevHELO\n");
...
}
...
}
The intention is for each mailfile from the parameter list to start
out with a clean value of $prevHELO, but if I specify two files to the
script then the second file is processed with the residual value of
$prevHELO from the first file.
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Tue, 07 Feb 2012 20:50:44 +0100
From: Peter Makholm <peter@makholm.net>
Subject: Re: Lifetime of my variables?
Message-Id: <87ehu6tobv.fsf@vps1.hacking.dk>
Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
> mailfile: while (my $mailfile=shift) {
...
> my $prevHELO;
...
> foreach (@Received[$ReceivedIx..$#Received]) {
>
> ...
>
> doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
> $+{BY1}, $+{BY2} // '') || last;
>
> ...
>
> sub doReceived {
> ...
>
> if ($prevHELO) {
It dives a bit into the gory parts of perl, but I think this is you
problem.
'sub doReceived' generates a function at compile time, refering to the
variable existing at compile time. Therefore it is not using the
variable initialized by the my statement in the outer loop.
Have you enabled 'use warnings' and 'use strict'?
I would think that at least one of them would catch this, but I'm not
quite sure which (as I'm not quite convinced about how perl actually
works for this example) and if the message is any meaningful.
//Makholm
------------------------------
Date: Tue, 07 Feb 2012 20:57:46 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Lifetime of my variables?
Message-Id: <87wr7y8iph.fsf@sapphire.mobileactivedefense.com>
Peter Makholm <peter@makholm.net> writes:
> Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
>
>
>> mailfile: while (my $mailfile=shift) {
> ...
>> my $prevHELO;
> ...
>> foreach (@Received[$ReceivedIx..$#Received]) {
>>
>> ...
>>
>> doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
>> $+{BY1}, $+{BY2} // '') || last;
>>
>> ...
>>
>> sub doReceived {
>> ...
>>
>> if ($prevHELO) {
>
> It dives a bit into the gory parts of perl, but I think this is you
> problem.
>
> 'sub doReceived' generates a function at compile time, refering to the
> variable existing at compile time. Therefore it is not using the
> variable initialized by the my statement in the outer loop.
The my-variable is exists in the lexical scope it is defined in and
since the subroutine is not defined inside the same lexical scope, it
uses the variable $prevHELO of the current package. Which will of
course keep its value unless the value is changed.
Perl code which achieves what was probably intended:
----------------
our $prevHELO;
while (<>) {
local $prevHELO;
print_it();
}
sub print_it()
{
print("|$prevHELO|");
$prevHELO = 'bla';
}
---------------
------------------------------
Date: Wed, 8 Feb 2012 00:38:13 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Lifetime of my variables?
Message-Id: <los809-vcl2.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Peter Makholm <peter@makholm.net> writes:
> > Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
> >
> >
> >> mailfile: while (my $mailfile=shift) {
> >> my $prevHELO;
> >> foreach (@Received[$ReceivedIx..$#Received]) {
> >> sub doReceived {
> >> if ($prevHELO) {
> >
> > It dives a bit into the gory parts of perl, but I think this is you
> > problem.
> >
> > 'sub doReceived' generates a function at compile time, refering to the
> > variable existing at compile time. Therefore it is not using the
> > variable initialized by the my statement in the outer loop.
>
> The my-variable is exists in the lexical scope it is defined in and
> since the subroutine is not defined inside the same lexical scope, it
> uses the variable $prevHELO of the current package. Which will of
> course keep its value unless the value is changed.
There are no package variables in the code Shmuel posted. The subroutine
is defined within the lexical scope of $prevHELO, otherwise it would
have given a strictures error.
Ben
------------------------------
Date: Wed, 8 Feb 2012 00:35:55 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Lifetime of my variables?
Message-Id: <bks809-vcl2.ln1@anubis.morrow.me.uk>
Quoth Peter Makholm <peter@makholm.net>:
> Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
>
>
> > mailfile: while (my $mailfile=shift) {
> ...
> > my $prevHELO;
> ...
> > foreach (@Received[$ReceivedIx..$#Received]) {
> >
> > ...
> >
> > doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
> > $+{BY1}, $+{BY2} // '') || last;
> >
> > ...
> >
> > sub doReceived {
> > ...
> >
> > if ($prevHELO) {
>
> It dives a bit into the gory parts of perl, but I think this is you
> problem.
>
> 'sub doReceived' generates a function at compile time, refering to the
> variable existing at compile time. Therefore it is not using the
> variable initialized by the my statement in the outer loop.
Yup. A named sub should never be defined inside a block which will
execute more than once. If you want a sub which will close over the
value of $prevHELO from outside, you can use an anonymous sub:
mailfile: while (...) {
my $prevHELO;
my $doReceived = sub { ... };
foreach (...) {
$doReceived->(...);
}
}
Otherwise you'll need to define doReceived outside the loop and pass
$prevHELO in as a parameter.
> Have you enabled 'use warnings' and 'use strict'?
>
> I would think that at least one of them would catch this, but I'm not
> quite sure which (as I'm not quite convinced about how perl actually
> works for this example) and if the message is any meaningful.
The relevant warning is 'Variable $x will not stay shared'. However, the
machinery which produces that warning is partially heuristic, and it
misses some cases. This is unfortunately one of them.
(In detail: because the while loop is at the top level of the program,
and because perl doesn't quite treat blocks which aren't subs as true
blocks, it doesn't realise that $prevHELO is declared in a section of
code which might run more than once.)
Ben
------------------------------
Date: Tue, 07 Feb 2012 20:53:34 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f31d59e$1$fuzhry+tra$mr2ice@news.patriot.net>
References: <4f311a37$1$fuzhry+tra$mr2ice@news.patriot.net>
<87lioeu4pt.fsf@vps1.hacking.dk>
<4f3169f6$1$fuzhry+tra$mr2ice@news.patriot.net>
<87ehu6tobv.fsf@vps1.hacking.dk>
Mail-Copies-To: nobody
Organization: Atid/2
X-Treme: C&C,DWS
X-WebTV-Stationery: Standard; BGColor=black; TextColor=black
In <87ehu6tobv.fsf@vps1.hacking.dk>, on 02/07/2012
at 08:50 PM, Peter Makholm <peter@makholm.net> said:
>Have you enabled 'use warnings' and 'use strict'?
Only use strict
>'sub doReceived' generates a function at compile time, refering to
>the variable existing at compile time. Therefore it is not using the
>variable initialized by the my statement in the outer loop.
Even though it is contained in the loop?
I get the same residual value with
mailfile: while (my $mailfile=shift) {
...
foreach (@Received[$ReceivedIx..$#Received]) {
...
doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
$+{BY1}, $+{BY2} // '') || last;
...
}
...
}
...
my $prevHELO;
sub doReceived {
my ($From, $HELO, $rDNS, $IP, $by1, $by2) = @_;
msg("\ndoReceived parameters:\n");
msg("\n\$From=$From\n");
msg("\n\$HELO=$HELO\n");
msg("\n\$rDNS=$rDNS\n");
msg("\n\$IP =$IP \n");
msg("\n\$by1 =$by1 \n");
msg("\n\$by2 =$by2 \n");
$HELO = uc $HELO;
$rDNS = uc $rDNS;
$IP = "[$IP]" unless $IP =~ /\[/;
my $goodHELO;
if ($MAIN::prevHELO) {
msg("\t\$prevHELO=$MAIN::prevHELO\n");
msg("\t\$prevSrc=$prevSrc\n");
unless (uc $by1 eq $MAIN::prevHELO or
"\U$by2.$by1" eq $MAIN::prevHELO or
uc $by1 eq $prevSrc or
"\U$by2.$by1" eq $prevSrc) {
$MAIN::prevHELO=$HELO;
msg("\t\$prevHELO after mismatch set to $MAIN::prevHELO\n");
return undef();
}
if ($prevBogus) {
msg("\tPrevious Received field was bad; skipping $From\n");
return undef();
}
} elsif ($lookup && $MARF) {
$host_info{$IP}{MARF}=1 if $IP;
$host_info{$rDNS}{MARF}=1 if $rDNS;
}
$MAIN::prevHELO=$HELO;
msg("\t\$prevHELO set to $MAIN::prevHELO\n");
$prevSrc=$rDNS;
$prevIP=$IP;
# Check for loopback or RFC 1918 source IP.
my $skipIP = localIP(inet_aton substr $IP, 1, -1);
$goodIP=$IP unless $skipIP;
$host_info{$IP}{skipIP}=$skipIP;
msg("\nDumper(\$skipIP)\n");
msg(Dumper($skipIP));
msg("\nDumper(\$goodIP)\n");
msg(Dumper($goodIP));
if ($skipIP) {
push @{$host_info{$goodIP}{msg}},
": the spam was routed via $skipIP IP $IP with HELO
$HELO\n";
return 1;
};
# Set up HELO and sent-from processing.
$_ = $HELO;
my $sent;
$sent = 'the spam was sent from';
$sent .= ' or relayed by' if /(?:$relayedDom)$/;
msg("\nTest HELO $HELO for IP or TLD\n");
# Don't process HELO/EHLO if it's TLD;
# validity check if it's IP address.
my $rDNSeff = $rDNS;
$rDNSeff =~ s/^\[$RE{net}{IPv4}\]$//o;
$rDNSeff =~ s/^$RE{net}{IPv4}$//o;
$rDNSeff =~ s/^[\w-]+$//o;
msg("\n\$rDNS=$rDNS, \$rDNSeff=$rDNSeff\n");
if (/^\[$RE{net}{IPv4}\]$/ || /^$RE{net}{IPv4}$/) {
msg("\nHELO $HELO is IP address.\n");
if ($IP eq $_) {
msg("\nHELO $HELO is matching and compliant IP address.\n");
$goodHELO = 1;
} elsif ($IP eq "[$_]") {
msg("\nHELO $HELO is matching but noncompliant IP
address.\n");
} else {
msg("\nHELO $HELO is bogus IP address.\n");
$prevBogus=1;
}
$host_info{$IP}{SMTP}{$rDNSeff.$IP} = $rDNSeff||$IP;
} elsif (/^[\w-]+$/ | $_ eq '.') {
msg("\nHELO $HELO not valid domain.\n");
$host_info{$IP}{SMTP}{$rDNSeff.$IP} = $rDNSeff||$IP;
} elsif ($rDNS eq $HELO) {
msg("\nrDNS $rDNS equal HELO $HELO\n");
$host_info{$IP}{SMTP}{$From} = $rDNS;
} else {
$goodHELO = 1;
$host_info{$HELO}{isHELO} = 1;
$host_info{$HELO}{SMTP}{$From} = $IP;
push @{$host_info{$HELO}{msg}},
": $sent $From\n";
$host_info{$IP}{SMTP}{$From} = $rDNS;
}
$host_info{$IP}{isIP} = 1;
msg("\n\$From from $From\n");
if ($goodHELO) {
push @{$host_info{$IP}{msg}},
": $sent $From in your IP space.\n";
} else {
push @{$host_info{$IP}{msg}},
": $sent $rDNSeff $IP in your IP space.\n";
}
if ($rDNS =~ /$notTLDpat/) {
$host_info{$rDNS}{SrcIP} = $IP;
$host_info{$rDNS}{SMTP}{$From} = $IP;
push @{$host_info{$rDNS}{msg}},
": $sent $From\n";
}
return 1;
}
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Wed, 8 Feb 2012 03:53:00 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Lifetime of my variables?
Message-Id: <s58909-86q2.ln1@anubis.morrow.me.uk>
Quoth Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>:
> In <87ehu6tobv.fsf@vps1.hacking.dk>, on 02/07/2012
> at 08:50 PM, Peter Makholm <peter@makholm.net> said:
>
> >'sub doReceived' generates a function at compile time, refering to
> >the variable existing at compile time. Therefore it is not using the
> >variable initialized by the my statement in the outer loop.
>
> Even though it is contained in the loop?
Yes. This is a necessary consequence of the fact that named subs are
global in scope and created at compile time; given something like
for my $x (1..4) {
sub foo { $x }
}
foo();
which instance of $x is foo goint to use? (The answer, in fact, is that
it uses the one from the first time the loop is entered, since that's
the one that existed at compile time.)
> I get the same residual value with
>
> mailfile: while (my $mailfile=shift) {
> ...
> foreach (@Received[$ReceivedIx..$#Received]) {
>
> ...
> doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
> $+{BY1}, $+{BY2} // '') || last;
> ...
> }
> ...
> }
> ...
>
>
> my $prevHELO;
> sub doReceived {
<snip>
> if ($MAIN::prevHELO) {
Um, *what* are you doing here? This is not the 'my $prevHELO' you just
declared, it's a global in the package MAIN (which doesn't usually
exist: the initial default package is called 'main', and package names
are case-sensitive).
(Do I owe Rainer an apology?)
Even if you had used the lexical, you should have expected to keep its
value across calls to the sub, since it is declared outside the scope of
the sub.
Ben
------------------------------
Date: Wed, 08 Feb 2012 05:31:41 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f324f0d$3$fuzhry+tra$mr2ice@news.patriot.net>
In <s58909-86q2.ln1@anubis.morrow.me.uk>, on 02/08/2012
at 03:53 AM, Ben Morrow <ben@morrow.me.uk> said:
>Um, *what* are you doing here?
Well, what I'm *trying* to do is to have a single variable named
$prevHELO that is used inside the while loop and maintained by the
subroutine. I thought that Rainer was suggesting that I prefix the
package name when using the variable inside the subroutine.
>the initial default package is called 'main'
Whoops!
>(Do I owe Rainer an apology?)
No; doReceived is inside the lexical scope, by design. Whether that
design is flawed is a separate issue :-(
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Wed, 08 Feb 2012 04:43:07 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f3243ab$1$fuzhry+tra$mr2ice@news.patriot.net>
In <bks809-vcl2.ln1@anubis.morrow.me.uk>, on 02/08/2012
at 12:35 AM, Ben Morrow <ben@morrow.me.uk> said:
>Otherwise you'll need to define doReceived outside the loop and pass
>$prevHELO in as a parameter.
Will moving the declaration before the while loop and explicitly
initializing the variable to undef at the beginning of the loop work?
my $prevHELO;
mailfile: while (my $mailfile=shift) {
undef $prevHELO;
...
foreach (@Received[$ReceivedIx..$#Received]) {
...
doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
$+{BY1}, $+{BY2} // '') || last;
...
}
...
sub doReceived {
...
if ($prevHELO) {
...
}
...
prevHELO=$HELO;
}
}
1
__END__
>(In detail: because the while loop is at the top level of the
>program, and because perl doesn't quite treat blocks which aren't
>subs as true blocks, it doesn't realise that $prevHELO is declared
>in a section of code which might run more than once.)
Is that reportable as a bug, and is it still the case in Perl 6?
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Tue, 07 Feb 2012 22:08:10 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: Lifetime of my variables?
Message-Id: <4f31e71a$1$fuzhry+tra$mr2ice@news.patriot.net>
In <87wr7y8iph.fsf@sapphire.mobileactivedefense.com>, on 02/07/2012
at 08:57 PM, Rainer Weikusat <rweikusat@mssgmbh.com> said:
>The my-variable is exists in the lexical scope it is defined in and
>since the subroutine is not defined inside the same lexical scope, it
>uses the variable $prevHELO of the current package.
The subroutine is inside the while loop, specifically to give it
access to variables declared in the loop.
>Perl code which achieves what was probably intended:
>----------------
>our $prevHELO;
>while (<>) {
> local $prevHELO;
> print_it();
>}
>sub print_it()
>{
> print("|$prevHELO|");
> $prevHELO = 'bla';
>}
>---------------
Doesn't that cause the subroutine to refer to a *different* variable
with the name $prevHELO?
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Wed, 08 Feb 2012 14:02:32 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Lifetime of my variables?
Message-Id: <87y5sdwhhj.fsf@sapphire.mobileactivedefense.com>
Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> Peter Makholm <peter@makholm.net> writes:
>> > Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid> writes:
>> >
>> >
>> >> mailfile: while (my $mailfile=shift) {
>> >> my $prevHELO;
>> >> foreach (@Received[$ReceivedIx..$#Received]) {
>> >> sub doReceived {
>> >> if ($prevHELO) {
>> >
>> > It dives a bit into the gory parts of perl, but I think this is you
>> > problem.
>> >
>> > 'sub doReceived' generates a function at compile time, refering to the
>> > variable existing at compile time. Therefore it is not using the
>> > variable initialized by the my statement in the outer loop.
>>
>> The my-variable is exists in the lexical scope it is defined in and
>> since the subroutine is not defined inside the same lexical scope, it
>> uses the variable $prevHELO of the current package. Which will of
>> course keep its value unless the value is changed.
>
> There are no package variables in the code Shmuel posted. The subroutine
> is defined within the lexical scope of $prevHELO, otherwise it would
> have given a strictures error.
It is not defined within this lexical scope in the incomplete code in
the article Peter Makholm replied to and I was referrring to as
well. I usually don't read 'Shmuels' postings because his a
signallless noise. Conceivably, he has also written other code than
this particular example and might have published it elsewhere.
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 3608
***************************************