Understanding Scope with 'my'

R

Roger

My code is this:

use warnings;
use strict;

my $number = my_rand();
print "The number is ".$number;
{ my $seed = 1;
sub my_rand (){

$seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;
return $seed;
}

I derived it from an article here: (apparently wrong??)
http://perl.plover.com/FAQs/Namespaces.html#glos_lexical_variable

The issue is that declaring 'seed' inside the brackets as shown above yields an
error of:
main::my_rand() called too early to check prototype at test_scope.pl line 6.
Use of uninitialized value in multiplication (*) at test_scope.pl line 11.

Basically I understand local, and am working on 'my' ... it would seem as if
using 'my' one needs to always use it in a sub in the context of returning it as
an lvalue...
like:
my $number = my_rand();
but like I said the code above does not work the way they:
http://perl.plover.com/FAQs/Namespaces.html#glos_lexical_variable
said it should or I am missing the big picture. BTW before I posted I read
'Learning Perl' 3rd edition... and prehaps I *should* have 'got it' from that
the example URL I reference above has me scratching my head...

TIA
 
B

Ben Morrow

Quoth Roger said:
My code is this:

use warnings;
use strict;

my $number = my_rand();
print "The number is ".$number;
{ my $seed = 1;

Why the bizzare indentation?
sub my_rand (){

$seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;
return $seed;
}

You have a missing } here.
I derived it from an article here: (apparently wrong??)
http://perl.plover.com/FAQs/Namespaces.html#glos_lexical_variable

No, this is a good basic description of how my and local work. The
problem is elsewhere.
The issue is that declaring 'seed' inside the brackets as shown above yields
an error of:
main::my_rand() called too early to check prototype at test_scope.pl line 6.
Use of uninitialized value in multiplication (*) at test_scope.pl line 11.

The problem is with these:

sub my_rand () {
^^

They are called a prototype, for which see perldoc perlsub. It will
suffice to say now that 1. they are an advanced feature of Perl and you
don't need to use them and 2. that perl needs to know a sub's prototype
*before* it encounters any calls to that sub (as the warning said).

The other warning comes from the fact that the assignment $seed = 1 is
not executed until after the call to my_rand. There are two fixes for
this: either move the whole block up above any calls to the sub, so that
the variable is initialised properly, or, better, make it into a BEGIN
block that will *definitely* be run before anything else. For BEGIN
blocks c.f. perldoc perlmod.

So, to fix your code you want

use warnings;
use strict;

# if you put
# use subs qw/my_rand/;
# here, you can call my_rand without parens

my $number = my_rand();
print "The number is $number\n";

BEGIN {
my $seed = 1;
sub my_rand { # Note: no ()
$seed = int (...);
return $seed;
}
}

Ben
 
R

Roger

"The other warning comes from the fact that the assignment $seed = 1 is
not executed until after the call to my_rand. There are two fixes for
this: either move the whole block up above any calls to the sub, so that
the variable is initialised properly, or, better, make it into a BEGIN
block that will *definitely* be run before anything else."

Yes that's right as it turns out. Just like a shell script if not for the BEGHIN
block. Thank you for pointing this out and I might say that URL I referenced
might be improved with this tidbit of info and the Llama book never explains
about begin blocks, although I'm sure it mentions the way the interpreter parses
a file... but then again the BEGIN block info is important to that.
Thanks again.
Roger
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top