Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Lexical array retaining elements from previous function invocations

Reply
Thread Tools

Lexical array retaining elements from previous function invocations

 
 
David McNerney
Guest
Posts: n/a
 
      05-04-2006
Hello all... I'm wondering if anyone can help me make sense of some
strange behavior that just bit me. It would appear that it's possible
for a lexical array declared inside a function to retain values between
function invocations, if said array is declared but not initialized in
a single-line "if" statement. I've reduced my problem to the test case
below, which performs per the comments on Perl 5.8.6 (Mac OSX Darwin)
and Perl 5.8.5 (Red Hat Linux Enterprise 4 Update 1). Much thanks in
advance for any insight anyone can provide. -- David

#!/usr/bin/perl -w
use strict;

sub function1
{
# PROBLEM HERE: if $_[0] is false here on successive invocations,
# @list is not cleared on the 2nd and later cycles, and any values
# added to it build up.
#
my @list = ("a") if $_[0];

# Uncomment this, and comment out the one above, and of course the
# strange behavior is gone
#
#my @list;

push(@list,"b") if $_[1];
print "list was: ".join(" ", @list)."\n";
}

&function1(1,1); # should print "a b", and does
&function1(1,0); # should print "a", and does
&function1(0,1); # should print "b", and does

# Problems begin here
#
&function1(0,0); # should print "", but prints "b"
&function1(0,1); # should print "b", but prints "b b"
&function1(0,1); # should print "b", but prints "b b b"
&function1(0,1); # should print "b", but prints "b b b b"
&function1(0,1); # should print "b", but prints "b b b b b"

# Ok again
#
&function1(1,0); # should print "a", and does

 
Reply With Quote
 
 
 
 
John W. Krahn
Guest
Posts: n/a
 
      05-04-2006
David McNerney wrote:
> Hello all... I'm wondering if anyone can help me make sense of some
> strange behavior that just bit me. It would appear that it's possible
> for a lexical array declared inside a function to retain values between
> function invocations, if said array is declared but not initialized in
> a single-line "if" statement. I've reduced my problem to the test case
> below, which performs per the comments on Perl 5.8.6 (Mac OSX Darwin)
> and Perl 5.8.5 (Red Hat Linux Enterprise 4 Update 1). Much thanks in
> advance for any insight anyone can provide. -- David
>
> #!/usr/bin/perl -w
> use strict;
>
> sub function1
> {
> # PROBLEM HERE: if $_[0] is false here on successive invocations,
> # @list is not cleared on the 2nd and later cycles, and any values
> # added to it build up.
> #
> my @list = ("a") if $_[0];


perldoc perlsyn
[snip]
NOTE: The behaviour of a "my" statement modified with a statement
modifier conditional or loop construct (e.g. "my $x if ...") is
undefined. The value of the "my" variable may be "undef", any
previously assigned value, or possibly anything else. Don't rely on
it. Future versions of perl might do something different from the
version of perl you try it out on. Here be dragons.



John
--
use Perl;
program
fulfillment
 
Reply With Quote
 
 
 
 
Brad Baxter
Guest
Posts: n/a
 
      05-04-2006
David McNerney wrote:
> Hello all... I'm wondering if anyone can help me make sense of some
> strange behavior that just bit me. It would appear that it's possible
> for a lexical array declared inside a function to retain values between
> function invocations, if said array is declared but not initialized in
> a single-line "if" statement. I've reduced my problem to the test case
> below, which performs per the comments on Perl 5.8.6 (Mac OSX Darwin)
> and Perl 5.8.5 (Red Hat Linux Enterprise 4 Update 1). Much thanks in
> advance for any insight anyone can provide. -- David
>
> #!/usr/bin/perl -w
> use strict;
>
> sub function1
> {
> # PROBLEM HERE: if $_[0] is false here on successive invocations,
> # @list is not cleared on the 2nd and later cycles, and any values
> # added to it build up.
> #
> my @list = ("a") if $_[0];
>
> # Uncomment this, and comment out the one above, and of course the
> # strange behavior is gone
> #
> #my @list;
>
> push(@list,"b") if $_[1];
> print "list was: ".join(" ", @list)."\n";
> }
>
> &function1(1,1); # should print "a b", and does
> &function1(1,0); # should print "a", and does
> &function1(0,1); # should print "b", and does
>
> # Problems begin here
> #
> &function1(0,0); # should print "", but prints "b"
> &function1(0,1); # should print "b", but prints "b b"
> &function1(0,1); # should print "b", but prints "b b b"
> &function1(0,1); # should print "b", but prints "b b b b"
> &function1(0,1); # should print "b", but prints "b b b b b"
>
> # Ok again
> #
> &function1(1,0); # should print "a", and does


This is a known issue. The answer is basically, don't do that.
Some people have taken advantage of this to intentionally
create static lexicals, but the behavior is not supported and
will likely quit working in future releases. Instead:

my @list;
@list = ("a") if $_[0];

--
Brad

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      05-04-2006
"David McNerney" <(E-Mail Removed)> wrote in
news:(E-Mail Removed) ups.com:

> sub function1
> {
> # PROBLEM HERE: if $_[0] is false here on successive invocations,
> # @list is not cleared on the 2nd and later cycles, and any values
> # added to it build up.
> #
> my @list = ("a") if $_[0];


If you had written this as:

if ( $_[0] ) {
my @list = ("a");
}

the problem with your code would have been clearer. Basically, putting
the declaration and initialization of @list in a compound if statement
causes ambiguity.

I am not sure why no warnings are emitted. I do remember a section in
the docs that deals with this but I am not able to locate it right now.

>
> # Uncomment this, and comment out the one above, and of course the
> # strange behavior is gone
> #
> #my @list;
>
> push(@list,"b") if $_[1];
> print "list was: ".join(" ", @list)."\n";
> }


Rewrite this sub as:

sub function1 {
my @list;
@list = qw( a ) if $_[0];
push @list, "b" if $_[1];
print "list was: @list\n";
}

> &function1(1,1); # should print "a b", and does


Don't use the ampersand in function invocations unless you know what it
does, and you specifically need that effect.

See perldoc perlsub

Sinan
--
A. Sinan Unur <(E-Mail Removed)>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc...uidelines.html

 
Reply With Quote
 
David McNerney
Guest
Posts: n/a
 
      05-05-2006
Thanks to everyone who replied. It does seem like a warning should be
emitted, but now that I know about it it won't bite me again at least!

 
Reply With Quote
 
David McNerney
Guest
Posts: n/a
 
      05-05-2006
Thanks for the info and the reminder.

I always use () with methods and functions, ie &foo(), never ever &foo,
and I've never dabbled in Perl prototypes, so the special behavior that
the ampersand brings with it hasn't bitten me in years. We usually use
object and class methods here, so it's kind of nice to have the & to
draw my attention to the rare use of a function in our code.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to add a row to the table web control dynamically in asp .net 2.0 on a button click retaining the user input in previous rows? loga123 ASP .Net 1 10-03-2006 04:48 AM
Log4j - dealing with multithreaded invocations? Piper707@hotmail.com Java 11 01-13-2006 03:25 AM
Web service invocations dilinig@eurocenter.lk Java 1 12-05-2005 07:12 PM
Lexical filehandles must be simple scalars (not eg hash elements) ? Richard Gration Perl Misc 3 01-11-2005 06:38 PM
rules engines: faster implementation than methods invocations? NOBODY Java 2 10-30-2004 04:19 AM



Advertisments