Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Lifetime of my variables?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  23 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Seymour J. Shmuel Metz  
View profile  
 More options Feb 7, 7:33 am
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Tue, 07 Feb 2012 07:33:59 -0500
Local: Tues, Feb 7 2012 7:33 am
Subject: Lifetime of my variables?
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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Makholm  
View profile  
 More options Feb 7, 8:56 am
Newsgroups: comp.lang.perl.misc
From: Peter Makholm <pe...@makholm.net>
Date: Tue, 07 Feb 2012 14:56:46 +0100
Local: Tues, Feb 7 2012 8:56 am
Subject: Re: Lifetime of my variables?
Shmuel (Seymour J.) Metz <spamt...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 7, 9:57 am
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Tue, 7 Feb 2012 14:57:20 +0000
Local: Tues, Feb 7 2012 9:57 am
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 7, 1:20 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Tue, 07 Feb 2012 13:20:32 -0500
Local: Tues, Feb 7 2012 1:20 pm
Subject: Re: Lifetime of my variables?
In <gnq709-7ff2....@anubis.morrow.me.uk>, on 02/07/2012
   at 02:57 PM, Ben Morrow <b...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 7, 1:14 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Tue, 07 Feb 2012 13:14:14 -0500
Local: Tues, Feb 7 2012 1:14 pm
Subject: Re: Lifetime of my variables?
In <87lioeu4pt....@vps1.hacking.dk>, on 02/07/2012
   at 02:56 PM, Peter Makholm <pe...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Makholm  
View profile  
 More options Feb 7, 2:50 pm
Newsgroups: comp.lang.perl.misc
From: Peter Makholm <pe...@makholm.net>
Date: Tue, 07 Feb 2012 20:50:44 +0100
Local: Tues, Feb 7 2012 2:50 pm
Subject: Re: Lifetime of my variables?
Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid> writes:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rainer Weikusat  
View profile  
 More options Feb 7, 3:57 pm
Newsgroups: comp.lang.perl.misc
From: Rainer Weikusat <rweiku...@mssgmbh.com>
Date: Tue, 07 Feb 2012 20:57:46 +0000
Local: Tues, Feb 7 2012 3:57 pm
Subject: Re: Lifetime of my variables?

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';
}

---------------

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 7, 7:38 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 00:38:13 +0000
Local: Tues, Feb 7 2012 7:38 pm
Subject: Re: Lifetime of my variables?

Quoth Rainer Weikusat <rweiku...@mssgmbh.com>:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 7, 7:35 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 00:35:55 +0000
Local: Tues, Feb 7 2012 7:35 pm
Subject: Re: Lifetime of my variables?

Quoth Peter Makholm <pe...@makholm.net>:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 7, 8:53 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Tue, 07 Feb 2012 20:53:34 -0500
Local: Tues, Feb 7 2012 8:53 pm
Subject: Re: Lifetime of my variables?
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....@vps1.hacking.dk>, on 02/07/2012
   at 08:50 PM, Peter Makholm <pe...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 7, 10:53 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 03:53:00 +0000
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:

> In <87ehu6tobv....@vps1.hacking.dk>, on 02/07/2012
>    at 08:50 PM, Peter Makholm <pe...@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.)

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 8, 5:31 am
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Wed, 08 Feb 2012 05:31:41 -0500
Local: Wed, Feb 8 2012 5:31 am
Subject: Re: Lifetime of my variables?
In <s58909-86q2....@anubis.morrow.me.uk>, on 02/08/2012
   at 03:53 AM, Ben Morrow <b...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 8, 4:43 am
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Wed, 08 Feb 2012 04:43:07 -0500
Local: Wed, Feb 8 2012 4:43 am
Subject: Re: Lifetime of my variables?
In <bks809-vcl2....@anubis.morrow.me.uk>, on 02/08/2012
   at 12:35 AM, Ben Morrow <b...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 7, 10:08 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Tue, 07 Feb 2012 22:08:10 -0500
Local: Tues, Feb 7 2012 10:08 pm
Subject: Re: Lifetime of my variables?
In <87wr7y8iph....@sapphire.mobileactivedefense.com>, on 02/07/2012
   at 08:57 PM, Rainer Weikusat <rweiku...@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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rainer Weikusat  
View profile  
 More options Feb 8, 9:02 am
Newsgroups: comp.lang.perl.misc
From: Rainer Weikusat <rweiku...@mssgmbh.com>
Date: Wed, 08 Feb 2012 14:02:32 +0000
Local: Wed, Feb 8 2012 9:02 am
Subject: Re: Lifetime of my variables?

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.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 8, 9:45 am
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 14:45:13 +0000
Local: Wed, Feb 8 2012 9:45 am
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:

> In <bks809-vcl2....@anubis.morrow.me.uk>, on 02/08/2012
>    at 12:35 AM, Ben Morrow <b...@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?

I'm still not entirely clear as to what you are trying to acheive: do
you want the value preserved across iterations of the foreach loop but
reset each time you restart the while loop? In that case yes, what you
suggest will work, but it's not a good way to write it.

In the first place, you still have sub doReceived inside the while loop.
Since it can't really be usefully considered to be within the scope of
the loop, it shouldn't be there.

Secondly, $prevHELO is now effectively a global you are using as a
parameter to doReceived. This is bad style for all the usual reasons, so
you should pass it as a normal parameter instead. Unless I've
misunderstood your logic, this isn't difficult:

> my $prevHELO;

> mailfile: while (my $mailfile=shift) {
>    undef $prevHELO;

$prevHELO logically belongs to (one iteration of) the while loop, so
this was the right place to declare it.

    my $prevHELO;

>    ...
>    foreach (@Received[$ReceivedIx..$#Received]) {
>      ...
>      doReceived($+{FROM}, $+{HELO} // $+{IP}, $+{RDNS} // '', $+{IP},
> $+{BY1}, $+{BY2} // '') || last;

Here, however, you need to pass it to doReceived explicitly rather than
assuming it can pick it up implicitly. The logic *is* a little awkward,
given that you want to 'last', but not enormously so. One way of writing
it would be

    my $HELO = $+{HELO} // $+{IP};
    my $more = doReceived($+{FROM}, $prevHELO, $HELO, ...);
    $prevHELO = $HELO;
    $more or last;

Another would be to return the new value for $prevHELO, which would be
better if you don't always want to set it to the HELO value passed in.

Yet another would be to pass a *ref* to $prevHELO, which doReceived can
use to set the value for itself; that's a little obscure, since it's
really just a hidden form of return value, but there are occasions where
the flexibility is useful.

Ben


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 8, 12:45 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 17:45:12 +0000
Local: Wed, Feb 8 2012 12:45 pm
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:

> In <s58909-86q2....@anubis.morrow.me.uk>, on 02/08/2012
>    at 03:53 AM, Ben Morrow <b...@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.

While that would work, at least if you included the 'undef $prevHELO'
you suggested xthread, it has no advantages over the file-scoped lexical
you were using there. As a general rule of thumb the only reason to ever
use package globals is if you (or some module, like Exporter) need to
get at the variable from outside the current file.

Ben


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rainer Weikusat  
View profile  
 More options Feb 8, 1:01 pm
Newsgroups: comp.lang.perl.misc
From: Rainer Weikusat <rweiku...@mssgmbh.com>
Date: Wed, 08 Feb 2012 18:01:17 +0000
Local: Wed, Feb 8 2012 1:01 pm
Subject: Re: Lifetime of my variables?

Ben Morrow <b...@morrow.me.uk> writes:
> Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:
>> In <s58909-86q2....@anubis.morrow.me.uk>, on 02/08/2012
>>    at 03:53 AM, Ben Morrow <b...@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.

> While that would work, at least if you included the 'undef $prevHELO'
> you suggested xthread,

It will also work when localizing $prevHELO during each loop-iteration.

> it has no advantages over the file-scoped lexical you were using
> there.

It has actually disadvantages: A my-Variable is accessed by indexing
into the appropriate lexical pad, ie, the name is resolved at compile
time, while accesing something which resides in the symbol table of
the package requires a symbol table aka 'hash' lookup.

> As a general rule of thumb the only reason to ever use package
> globals is if you (or some module, like Exporter) need to get at the
> variable from outside the current file.

The other reason would be local: It is possible to create a binding
for a package-global variable which only exists during the dynamic
extent of the lexical scope that established it.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 8, 1:26 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Wed, 8 Feb 2012 18:26:10 +0000
Local: Wed, Feb 8 2012 1:26 pm
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:

> In <bks809-vcl2....@anubis.morrow.me.uk>, on 02/08/2012
>    at 12:35 AM, Ben Morrow <b...@morrow.me.uk> said:

> >(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?

[I realise I didn't answer this bit...]

No, there would be no point reporting it as a bug. Anyone who might be
capable of fixing it is already well aware this is how perl behaves, and
why.

It's a performance tradeoff: in order to avoid the (relatively large)
overhead of setting up a new lexical pad and pulling down the outer
lexicals every time a block is entered, perl cheats and lifts the
lexicals for a block up into the innermost surrounding sub. A certain
amount of bookkeeping is required to make sure they don't end up visible
when they shouldn't have been, but nearly all of that happens at compile
time. Once a block has been compiled it's rather difficult to work out
which section of code a given lexical was originally attached to.

I don't know if it's still the case in Perl 6 (I don't know much about
it) but I suspect not. I believe that at least in principle all blocks
is Perl 6 are true lexical closures; while I'm certain the various
implementations do a certain amount of cheating (since otherwise
performance would be appalling) I suspect the continuation-based control
flow means they are obliged to keep more careful track of lexical scopes
at runtime.

Ben


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 8, 3:27 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Wed, 08 Feb 2012 15:27:53 -0500
Local: Wed, Feb 8 2012 3:27 pm
Subject: Re: Lifetime of my variables?
In <2bra09-5g6....@anubis.morrow.me.uk>, on 02/08/2012
   at 06:26 PM, Ben Morrow <b...@morrow.me.uk> said:

>I don't know if it's still the case in Perl 6 (I don't know much
>about it) but I suspect not.

Thanks. In the meantime, I've moved the subroutines and the variables
they refer to out of the loop amd that seems to have taken care of
things.

--
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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 8, 3:51 pm
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Wed, 08 Feb 2012 15:51:34 -0500
Local: Wed, Feb 8 2012 3:51 pm
Subject: Re: Lifetime of my variables?
In <pcea09-v14....@anubis.morrow.me.uk>, on 02/08/2012
   at 02:45 PM, Ben Morrow <b...@morrow.me.uk> said:

>I'm still not entirely clear as to what you are trying to acheive: do
>you want the value preserved across iterations of the foreach loop
>but reset each time you restart the while loop?

Yes.

>In that case yes, what you suggest will work, but it's not a
>good way to write it.

The alternatives I'm aware of all seem more awkward.

>so you should pass it as a normal parameter instead.

I'd have to pass it as a reference, which seems more awkward than
having it in a common scope.

>    my $HELO = $+{HELO} // $+{IP};
>    my $more = doReceived($+{FROM}, $prevHELO, $HELO, ...);
>    $prevHELO = $HELO;
>    $more or last;

That would defeat my intent of relegating the logic to the subroutine.

>Another would be to return the new value for $prevHELO, which would
>be better if you don't always want to set it to the HELO value
>passed in.

There is more than one variable that must be updated.

--
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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Seymour J. Shmuel Metz  
View profile  
 More options Feb 10, 10:27 am
Newsgroups: comp.lang.perl.misc
From: Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>
Date: Fri, 10 Feb 2012 10:27:39 -0500
Local: Fri, Feb 10 2012 10:27 am
Subject: Re: Lifetime of my variables?
In <2bra09-5g6....@anubis.morrow.me.uk>, on 02/08/2012
   at 06:26 PM, Ben Morrow <b...@morrow.me.uk> said:

>No, there would be no point reporting it as a bug. Anyone who might
>be capable of fixing it is already well aware this is how perl
>behaves, and why.

What about the fact that neither use strcit nor use warnings catches
it?

--
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 spamt...@library.lspace.org


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Morrow  
View profile  
 More options Feb 10, 3:37 pm
Newsgroups: comp.lang.perl.misc
From: Ben Morrow <b...@morrow.me.uk>
Date: Fri, 10 Feb 2012 20:37:44 +0000
Local: Fri, Feb 10 2012 3:37 pm
Subject: Re: Lifetime of my variables?

Quoth Shmuel (Seymour J.) Metz <spamt...@library.lspace.org.invalid>:

> In <2bra09-5g6....@anubis.morrow.me.uk>, on 02/08/2012
>    at 06:26 PM, Ben Morrow <b...@morrow.me.uk> said:

> >No, there would be no point reporting it as a bug. Anyone who might
> >be capable of fixing it is already well aware this is how perl
> >behaves, and why.

> What about the fact that neither use strcit nor use warnings catches
> it?

Again, that's well known. For instance, pad.c (which handles lexicals)
has this comment (in S_pad_findlex)

                /* set PAD_FAKELEX_MULTI if this lex can have multiple
                 * instances. For now, we just test !CvUNIQUE(cv), but
                 * ideally, we should detect my's declared within loops
                 * etc - this would allow a wider range of 'not stayed
                 * shared' warnings. We also treated already-compiled
                 * lexes as not multi as viewed from evals. */

which precisely explains the problem.

Warnings are generally considered best-effort, given that (in principle)
they're only warning you about things you ought to have known already.
If a few cases are missed because it would be rather difficult to catch
them, that's considered an acceptable trade-off.

Ben


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »