For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > January 2008 > Strange interaction of "my"-variables with initialization









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Strange interaction of "my"-variables with initialization
Peter Daum

2008-01-13, 8:00 am

Hi,

I just got bitten by a very simple issue, where Perl behaves totally
different from what I had expected;

According to the documentation, lexical variables are visible only after
the line they have been declared in; they may be initialized;
otherwise their value is undefined, so the following short code snippet:

foreach (qw(a b c)) {
my $t;
warn("\$t == ", $t||'undef', "\n");
$t=$_;
}

will 3 times print "$t == undef" (as to be expected).
Now a minor variation:

my $x=undef;
foreach (qw(a b c)) {
my $t =$x if $x;
warn("\$t == ", $t||'undef', "\n");
$t=$_;
}

$t would be initialized with the value of $x if that was true;
otherwise (at least that's what I would expect) $t should be undefined,
so the result would be as before. The real outcome, however, is:

$t == undef
$t == a
$t == b

$t now retains its value from the last loop iteration.
Is this a bug or a feature (tm)?
If it is a feature, then why isn't the value also retained in the 1st example?

Regards,
Peter Daum

John W. Krahn

2008-01-13, 8:00 am

Peter Daum wrote:
> Hi,


Hello,

> I just got bitten by a very simple issue, where Perl behaves totally
> different from what I had expected;
>=20
> According to the documentation, lexical variables are visible only afte=

r
> the line they have been declared in; they may be initialized;
> otherwise their value is undefined, so the following short code snippet=

:
>=20
> foreach (qw(a b c)) {
> my $t;
> warn("\$t =3D=3D ", $t||'undef', "\n");
> $t=3D$_;
> }
>=20
> will 3 times print "$t =3D=3D undef" (as to be expected).
> Now a minor variation:
>=20
> my $x=3Dundef;
> foreach (qw(a b c)) {
> my $t =3D$x if $x;
> warn("\$t =3D=3D ", $t||'undef', "\n");
> $t=3D$_;
> }
>=20
> $t would be initialized with the value of $x if that was true;
> otherwise (at least that's what I would expect) $t should be undefined,=


> so the result would be as before. The real outcome, however, is:
>=20
> $t =3D=3D undef
> $t =3D=3D a
> $t =3D=3D b
>=20
> $t now retains its value from the last loop iteration.
> Is this a bug or a feature (tm)?
> If it is a feature, then why isn't the value also retained in the 1st e=

xample?

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=92t 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
--=20
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

Chas. Owens

2008-01-13, 7:01 pm

On Jan 13, 2008 6:22 AM, Peter Daum <gator_ml@yahoo.de> wrote:
snip
> my $t =$x if $x;

snip
> $t would be initialized with the value of $x if that was true;
> otherwise (at least that's what I would expect) $t should be undefined,
> so the result would be as before. The real outcome, however, is:
>
> $t == undef
> $t == a
> $t == b
>
> $t now retains its value from the last loop iteration.
> Is this a bug or a feature (tm)?
> If it is a feature, then why isn't the value also retained in the 1st example?

snip

People argue about whether this is a bug or not*. In my opinion, it
is a bug because the variable's scope should be within the if
statement. You wouldn't expect to be able the use the variable if the
code looked like this

if ($x) {
my $t = $x;
}
print "$t\n";

so why should you be able to use it because it has been changed to this

my $t = $x if $x;
print "$t\n";

The proper way to get static variables prior to Perl 5.10 is

{
my $counter;
sub inc {
return $counter++;
}
}

With Perl 5.10 we can use state** instead of my:

sub inc {
state $counter;
return $counter++;
}

* http://www.perlmonks.org/?node_id=95940
** http://perldoc.perl.org/functions/state.html
John W. Krahn

2008-01-13, 7:01 pm

Chas. Owens wrote:
> On Jan 13, 2008 6:22 AM, Peter Daum <gator_ml@yahoo.de> wrote:
> snip
> snip
> snip
>
> People argue about whether this is a bug or not*. In my opinion, it
> is a bug because the variable's scope should be within the if
> statement.


Statements don't define scope, braces and files define scope.

> You wouldn't expect to be able the use the variable if the
> code looked like this
>
> if ($x) {
> my $t = $x;
> }


The scope is limited because of the braces.

> print "$t\n";
>
> so why should you be able to use it because it has been changed to this
>
> my $t = $x if $x;
> print "$t\n";


You can use it because it is in the same scope.



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
Chas. Owens

2008-01-13, 7:01 pm

On Jan 13, 2008 1:20 PM, John W. Krahn <krahnj@telus.net> wrote:
snip
> Statements don't define scope, braces and files define scope.

snip
>
> You can use it because it is in the same scope.

snip

And that is why I consider it to be a bug. There is no reason for
conditional modifiers to not have their own scope. For instance, the
conditional form of for still localizes $_, even though there is no
scope for it to be localized in:

#!/usr/bin/perl

use strict;
use warnings;

$_ = "foo";
print "$_\n" for "bar";
print "$_\n";
John W. Krahn

2008-01-13, 7:01 pm

Chas. Owens wrote:
> On Jan 13, 2008 1:20 PM, John W. Krahn <krahnj@telus.net> wrote:
> snip
> snip
is[color=darkred]
> snip
>=20
> And that is why I consider it to be a bug. There is no reason for
> conditional modifiers to not have their own scope. For instance, the
> conditional form of for still localizes $_, even though there is no
> scope for it to be localized in:


This is just the way that Perl works:

perldoc perlsyn
[ SNIP ]
Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the
variable is preceded with the keyword "my", then it is lexically
scoped, and is therefore visible only within the loop. Otherwise,
the variable is implicitly local to the loop and regains its former
value upon exiting the loop. If the variable was previously
declared with "my", it uses that variable instead of the global one,=

but it=92s still localized to the loop. This implicit localisation
occurs only in a "foreach" loop.

The same localization of $_ also occurs with map and grep.

$ perl -le'
$_ =3D "foo";
map $_ +=3D 1, @x =3D 1 .. 3;
print "$_ @x";
'
foo 2 3 4


John
--=20
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

Dr.Ruud

2008-01-14, 8:01 am

Peter Daum schreef:

> my $x = undef;
> foreach ( qw(a b c) ) {
> my $t = $x if $x;
> warn( "\$t == ", $t||'undef', "\n" );
> $t = $_;
> }
>
> $t would be initialized with the value of $x if that was true;
> otherwise (at least that's what I would expect) $t should be
> undefined,
> so the result would be as before. The real outcome, however, is:
>
> $t == undef
> $t == a
> $t == b
>
> $t now retains its value from the last loop iteration.
> Is this a bug or a feature (tm)?


In a short and positive way:
The runtime-actions attached to my(), which include resetting the value,
are skipped when the condition says so.

--
Affijn, Ruud

"Gewoon is een tijger."

Uri Guttman

2008-01-14, 7:02 pm

>>>>> "R" == Ruud <rvtol> writes:
[color=darkred]

R> In a short and positive way:
R> The runtime-actions attached to my(), which include resetting the value,
R> are skipped when the condition says so.

and it is a BUG. it goes away in 5.10. using it is wrong and will break
under perl after 5.10. use a my var in an outer scope or a state
variable in 5.10. do not use this BUG for any real code or you will get
burned.

it just happened to do this and it is NOT specified in the docs so it is
a BUG.

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Architecture, Development, Training, Support, Code Review ------
----------- Search or Offer Perl Jobs ----- http://jobs.perl.org ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com