Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

static variable problem

80 views
Skip to first unread message

Dave Saville

unread,
Nov 13, 2012, 8:38:07 AM11/13/12
to
Please why does this throw an error?

[T:\tmp]cat try.pl
use strict;
use warnings;

foo("Hello World");
exit;
{
my $bar = 1;

sub foo
{
my $a = shift;
print "$bar $a\n"; # <== line 12
return;
}
}

[T:\tmp]try.pl
Use of uninitialized value in concatenation (.) or string at try.pl
line 12.
Hello World

So $bar is private to foo - but you can't initialise it?

TIA
--
Regards
Dave Saville

Rainer Weikusat

unread,
Nov 13, 2012, 9:28:18 AM11/13/12
to
"Dave Saville" <da...@invalid.invalid> writes:
> Please why does this throw an error?
>
> [T:\tmp]cat try.pl
> use strict;
> use warnings;
>
> foo("Hello World");
> exit;
> {
> my $bar = 1;
>
> sub foo
> {
> my $a = shift;
> print "$bar $a\n"; # <== line 12
> return;
> }
> }
>
> [T:\tmp]try.pl
> Use of uninitialized value in concatenation (.) or string at try.pl
> line 12.
> Hello World

Because $bar = 1 is never executed: The compiler compiles this, then
the program invokes the foo subroutine and exits before the $bar = 1.
You can move the foo("Hello World") below the block or use BEGIN or
INIT to ensure that $bar is actually initialized:

----------
use strict;
use warnings;

foo("Hello World");
exit;
{
my $bar;

INIT {

Ben Morrow

unread,
Nov 13, 2012, 9:45:03 AM11/13/12
to

Quoth "Dave Saville" <da...@invalid.invalid>:
> Please why does this throw an error?
>
> [T:\tmp]cat try.pl
> use strict;
> use warnings;
>
> foo("Hello World");
> exit;
> {
> my $bar = 1;
>
> sub foo
> {
> my $a = shift;
> print "$bar $a\n"; # <== line 12
> return;
> }
> }
>
> [T:\tmp]try.pl
> Use of uninitialized value in concatenation (.) or string at try.pl
> line 12.

This is not an error, it is a warning.

> Hello World
>
> So $bar is private to foo - but you can't initialise it?

You call foo() before $bar is initialised. Move the call after the block
and it will do what you expect.

Ben

Rainer Weikusat

unread,
Nov 13, 2012, 2:01:21 PM11/13/12
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:
> "Dave Saville" <da...@invalid.invalid> writes:
>> Please why does this throw an error?
>>
>> [T:\tmp]cat try.pl
>> use strict;
>> use warnings;
>>
>> foo("Hello World");
>> exit;
>> {
>> my $bar = 1;
>>
>> sub foo
>> {
>> my $a = shift;
>> print "$bar $a\n"; # <== line 12
>> return;
>> }
>> }
>>
>> [T:\tmp]try.pl
>> Use of uninitialized value in concatenation (.) or string at try.pl
>> line 12.
>> Hello World
>
> Because $bar = 1 is never executed: The compiler compiles this, then
> the program invokes the foo subroutine and exits before the $bar =
> 1.

Additional explanation: Generally, running a Perl program is comprised
of two phases: A compilation step where the Perl compiler reads all
the source code files and transforms the code into some internal
representation (AFAIK called 'an optree') and an execution phase where
the Perl interpreter evaluates/ executes this 'optree'. This means any
statement in a Perl program may have run time or compile time effects
or both and the run time effects aren't visible during compile
time. For this example, this means the compiler creates a compiled
subroutine 'foo' which refers to the $bar defined in the outer block
because 'creating my variables' has the compile-time effect of making
the corresponding names visible to the compiler (so that it can
generated code accessing the proper objects). But the assignment to
$bar does not happen at compile-time, it happens at run-time when the
corresponding statement is executed. An execution of the 'content' of
a file is top-to-bottom: By the time the foo("...:") is executed, a
subroutine referencing the proper $bar has been created but the value
of $bar hasn't yet been set.

So-called 'BEGIN block' can be used to execute Perl code at
compile-time and alternatively, so-called 'INIT blocks' can be used to
run Perl code after the compilation phase has finished and before any
of the 'general' code ran (details are in the perlmod manpage).

C.DeRykus

unread,
Nov 13, 2012, 2:30:51 PM11/13/12
to
And just for a spaghetti western :)


goto BLOCK;

FOO: foo("Hello World");
exit;

BLOCK: {
my $bar = 1;

sub foo
{
my $a = shift;
print "$bar $a\n";
return;
}
goto FOO;
};
__END__

[ duck ] C.DeRykus

Rainer Weikusat

unread,
Nov 14, 2012, 8:23:46 AM11/14/12
to
"C.DeRykus" <der...@gmail.com> writes:

[...]

> goto BLOCK;
>
> FOO: foo("Hello World");
> exit;
>
> BLOCK: {
> my $bar = 1;
>
> sub foo
> {
> my $a = shift;
> print "$bar $a\n";
> return;
> }
> goto FOO;
> };

In contrast to 'other languages', the destination of a Perl goto is
determined at runtime, by 'outward' searching (IIRC, term used by the
Camel book) for a matching label in all currently active lexical
scopes. This implies that, compared to other means for performing flow
control, it is a very expensive operation.

--------------
use Benchmark;

timethese(-5,
{
goto => sub {
goto out;

print "ha!";

out:
return 3;
},

return => sub {
return 3;
}});

C.DeRykus

unread,
Nov 14, 2012, 6:29:20 PM11/14/12
to
Thanks, that's interesting. I would have
thought that it'd be much cheaper. Of course,
spaghetti code is super bad anyway for all
the reasons we know about. You gotta have
Clint Eastwood's steely gaze and grit to
follow the crooked trails and dodge bullets
that might ricochet anywhere.

That's why I said "duck".

--
Charles DeRykus

da...@deezee.org

unread,
Nov 15, 2012, 6:22:09 AM11/15/12
to
Thanks all. I was a bit confused because my test was pasted straight out of perldocs. :-)

Sorry for the late response but I am having problems with my newsreader and never saw my own post nor any of the replies. Had to log into Google to send this - Yuk I hate web groups.

Keith Thompson

unread,
Nov 15, 2012, 3:46:01 PM11/15/12
to
Where exactly in the Perl docs did you find that code?

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
0 new messages