global variable in a subroutine

global variable in a subroutine

am 23.01.2006 18:11:22 von kelly

Hi,
I'm having problem with my global variables.
If I rewrote the program below not to have subroutines
then it works. When I try to separate them with subroutines
I get an error:
Global symbol "$hostname" requires explicit package name at
time_execution.pl li
ne 96.
When I remove the "my", I still get an error. If not the direct anwer
on what I should do, I would appeciate on what to read on on perl. tx.


#!/usr/bin/perl
use strict;
use warnings;
use File::stat;
use Tie::File;

sub main() {
get_hostname();
create_report();
}

sub get_hostname() {
my $hostname = qx(hostname);
print "hostname is $hostname\n";
}

sub create_report() {
my @tmpa;
push (@tmpa, $hostname);
push (@tmpa, "test1");
push (@tmpa, "test2");
}

main();

Re: global variable in a subroutine

am 23.01.2006 18:43:09 von Gunnar Hjalmarsson

kelly wrote:
> I'm having problem with my global variables.

There are no global variables in your program, so how can you have
problems with them? ;-)

> I get an error:
> Global symbol "$hostname" requires explicit package name at
> time_execution.pl line 96.

The $hostname variable is lexically scoped to the get_hostname()
function. To use its value somewhere else, you should have
get_hostname() return the value, and then e.g. pass it so some other
function.

sub main() {
my $hostname = get_hostname();
create_report($hostname);
}

sub get_hostname {
...
return $hostname;
}

sub create_report {
my $hostname = shift;
...
}

I think "perldoc perlsub" explains it further.

HTH

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: global variable in a subroutine

am 23.01.2006 18:52:11 von Paul Lalli

kelly wrote:

> I'm having problem with my global variables.

You do not have any global variables. That is a *good* thing.

> If I rewrote the program below not to have subroutines
> then it works. When I try to separate them with subroutines
> I get an error:
> Global symbol "$hostname" requires explicit package name at
> time_execution.pl line 96.
> When I remove the "my", I still get an error.

That error is telling you that you have not declared any variable
$hostname within the scope of line 96, where it is used.

Do not remove the my. my is what we use to declare lexical variables.
Unless you have a very good reason to use global variables (and you
don't), use lexicals.

Your problem is that you are declaring your variable in one scope, (ie,
within one { } block), but trying to use it in another. You can't do
that.

> #!/usr/bin/perl
> use strict;
> use warnings;
> use File::stat;
> use Tie::File;
>

Two options. Option 1 is to declare your lexical variable here, rather
than in the subroutine:

my $hostname;

> sub main() {
> get_hostname();
> create_report();

Option 2 is to have get_hostname return the value, and pass that value
to create_report, within this "main" subroutine.:

my $hostname = get_hostname();
create_report($hostname);

> }
>
> sub get_hostname() {
> my $hostname = qx(hostname);

Under option 1, remove the 'my' here, since the variable was declared
above. Under option 2, leave the 'my', since you're declaring a
variable here, assigning to it, . . .

> print "hostname is $hostname\n";

.. . . and then returning that variable's value here:

return $hostname;

> }
>
> sub create_report() {
> my @tmpa;
> push (@tmpa, $hostname);
> push (@tmpa, "test1");
> push (@tmpa, "test2");
> }
>
> main();

Please note that in Perl, it is very uncommon to have a "main"
subroutine. Just put the code that you want to call directly. That
is, replace this call to "main" with the statements that you currently
have in the main() definition. (And then of course, remove the
definition of main as well).

For more on scoping issues with Perl, read:
perldoc perlsub
and Google for
"Coping with Scoping"

Hope this helps,
Paul Lalli

Re: global variable in a subroutine

am 23.01.2006 18:55:03 von Paul Lalli

Paul Lalli wrote:
> kelly wrote:
>
> > sub create_report() {

Sorry. I forgot to point out that under option 2, you'll need to
obtain the value that you passed into create_report:

my $hostname = shift;
OR
my ($hostname) = @_;
OR
my $hostname = $_[0];

(the first statement above is generally the most common way to do it)

> > my @tmpa;
> > push (@tmpa, $hostname);
> > push (@tmpa, "test1");
> > push (@tmpa, "test2");
> > }

Paul Lalli