use one subroutine's variable value in another subroutine inside a module.

K

king

I have a module named TPWizardMgr.pm as below.

========================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# reset all data
$self->{load_school_template} = {};
$self->{get_course_info} = {};

# load school types from config file
$self->{load_school_template} = [];
$self->{get_course_info} = [];

return $self;
}


sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc-
getElementsByTagName('subject-templates'))
{
$len = $school_template-
getElementsByTagName('subject-template')->getLength() ;
@years =
('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template-
getElementsByTagName('subject-template')->item($i); $subject_name = $item-
getAttribute('name');
for my $count (0..4)
{
$periods = $item-
getAttribute($years[$count]);
push
(@template_subject_period, [$subject_name,$years[$count], $periods]);
}
}
}

return @template_subject_period;
}

sub get_course_info
{
my $self = shift;
my $subject_name = shift;
my @years = shift;
my $periods = shift;
my $count = shift;
my @template_subject_period = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);
for(my $i=0;$i <= $#template_subject_period;$i++)
{
print $#template_subject_period . "\n";
print "inside for loop\n";
if($template_subject_period[$i]->[1] eq $gotperiod)
{
push (@template_subject_period,
[$subject_name,$years[$count], $periods]);

print "Subject:\t" .
$template_subject_period[$i]->[0] . $template_subject_period[$i]-
[2] . "\n";
}
}
return $self->{get_course_info};
}

1;
==================================================================

But I want to use the variable @template_subject_period in the
subroutine get_course_info( ).

I am not able to use this @template_subject_period variable value in
the get_course_info subroutine.

How I can do this.

Thanks in advance.
 
M

Mumia W.

I have a module named TPWizardMgr.pm as below.
[ 50+ lines of code snipped ]

But I want to use the variable @template_subject_period in the
subroutine get_course_info( ).

I am not able to use this @template_subject_period variable value in
the get_course_info subroutine.

How I can do this.

Thanks in advance.

Since @template_subject_period was declared with "my," it is restricted
to the scope of get_course_info. The solution is to make the variable a
package variable; declare it with "our."

You can access the variable from other packages as
@TPWizardMgr::template_subject_period. Since you're creating a class, a
more object oriented approach would be to make the variable accessible
through a class method, e.g:

sub template_subject_period {
my $class = shift;
our @template_subject_period;
return \@template_subject_period;
}

Since the above method returns an array reference, you would have to be
comfortable using array references. If not, just use the other solution
above.
 
B

Brian McCauley

I have a module named TPWizardMgr.pm as below.
sub load_school_template
{
my $self = shift; #...
my @template_subject_period;
# Put lots of stuff in @template_subject_period;
}

sub get_course_info
{
my $self = shift;
# Stuff that needs @template_subject_period calculated above
}

1;
==================================================================

But I want to use the variable @template_subject_period in the
subroutine get_course_info( ).

I am not able to use this @template_subject_period variable value in
the get_course_info subroutine.

No because it's lexically scoped to the other subroutine.

If you want data that persists from one method call to another you
store it _in_the_object_.


How I can do this.


sub load_school_template
{
my $self = shift;
#...
# Put lots of stuff in @{$self->{template_subject_period}};
}

sub get_course_info
{
my $self = shift;
# Stuff that uses @{$self->{template_subject_period}};
}


Now I've answered the question you asked I'll compose another follow-
up that addresses some other issues with your code.
 
I

injunjoel

Greetings,
Here are my suggestions based on what I understood from your post.
Read the comments at the bottom for more details.

==========================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# load school types from config file
$self->load_school_template();

#From the looks of it you don't need to call this
#when you create the object so leave it out.
#$self->get_course_info();

return $self;

}

sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc-
getElementsByTagName('subject-templates'))
{
$len = $school_template->getElementsByTagName('subject-
template')->getLength() ;

@years
=('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template-
getElementsByTagName('subject-template')->item($i);

$subject_name = $item->getAttribute('name');

for my $count (0..4)
{
$periods = $item-
getAttribute($years[$count]);

#you created a blessed hash for your object structure... USE
IT! #here we nest a bunch of stuff in the object hash
# $self->{'subject_period'} contains a hash with
# $subject_name as keys which contains a hash with
# @years as keys so 'periods_1','periods_2', etc...
# with a array of what ever came out of $periods
#
#this is all to facilitate your lookup in get_course_info();
push (@{$self->{'subject_period'}-
{$subject_name}->{$years[$count]}}, $periods);
}
}
}
return 1;
}

sub get_course_info
{

# This is now just a method of the underlying object hash
# call it with the subject name as the only argument


my $self = shift;
my $subject_name = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);

#lets check shall we?
if($gotperiod < 1 || $gotperiod > 5)
{
print "Period out of range.\nValid range is 1-5!\n";
return undef;
}

#standardize the periods key if they only entered a number.
$gotperiod = 'periods_'.$gotperiod if($gotperiod !~ /^periods_/);

#check if this is even a valid key/subject
if(exists($self->{'subject_period'}->{$subject_name}))
{
#do the lookup for this subject.
my @courses = @{$self->{'subject_period'}->{$subject_name}-
{$gotperiod}};

#print what we found from our lookup.
foreach my $course (@courses)
{
print "Subject:\t" . $subject_name . . "\n";
}
}
else {
print "Subject: $subject_name was not found!\n";
return undef;
}

return 1;
}

sub get_subject_names
{
$self = shift;
return sort {$a cmp $b} keys @{$self->{'subject_period'}};
}

1;


#
# sample usage:
# my $obj = TPWizardMgr->new();
# my @subjects = $obj->get_subject_names;
# foreach my $subject (@subjects)
# {
# $obj->get_course_info($subject);
# }
#
#
#
#


==========================================================================



I have a module named TPWizardMgr.pm as below.

========================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# reset all data
$self->{load_school_template} = {};
$self->{get_course_info} = {};

# load school types from config file
$self->{load_school_template} = [];
$self->{get_course_info} = [];

return $self;

}

sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc->getElementsByTagName('subject-templates'))

{
$len = $school_template->getElementsByTagName('subject-template')->getLength() ;

@years =
('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template->getElementsByTagName('subject-template')->item($i);

$subject_name = $item->getAttribute('name');

for my $count (0..4)
{
$periods = $item->getAttribute($years[$count]);

push
(@template_subject_period, [$subject_name,$years[$count], $periods]);
}
}
}

return @template_subject_period;

}

sub get_course_info
{
my $self = shift;
my $subject_name = shift;
my @years = shift;
my $periods = shift;
my $count = shift;
my @template_subject_period = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);
for(my $i=0;$i <= $#template_subject_period;$i++)
{
print $#template_subject_period . "\n";
print "inside for loop\n";
if($template_subject_period[$i]->[1] eq $gotperiod)
{
push (@template_subject_period,
[$subject_name,$years[$count], $periods]);

print "Subject:\t" .
$template_subject_period[$i]->[0] . $template_subject_period[$i]->[2] . "\n";

}
}
return $self->{get_course_info};

}

1;
==================================================================

But I want to use the variable @template_subject_period in the
subroutine get_course_info( ).

I am not able to use this @template_subject_period variable value in
the get_course_info subroutine.

How I can do this.

Thanks in advance.
 
B

Brian McCauley

I have a module named TPWizardMgr.pm as below.

========================================================================
package TPWizardMgr;
use strict;

Good, but you forgot "use warnings". Even tying only one hand behind
your back makes life difficult.
use XML::DOM;
sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# reset all data
$self->{load_school_template} = {};
$self->{get_course_info} = {};
Why?

# load school types from config file

A comment should describe things about what the code is doing that are
not obvious from looking at it.

It should not describe things about what the code is doing that are
obvious from looking at it.

It should not assert that the code is doing something that it's not.
$self->{load_school_template} = [];
$self->{get_course_info} = [];
What!?

return $self;

}

sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;

That's a very very nasty case of premature declaration you've got
there. You should take something for it.
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc->getElementsByTagName('subject-templates'))

{
$len = $school_template->getElementsByTagName('subject-template')->getLength() ;

@years =
('periods_1','periods_2','periods_3','periods_4','periods_5');

@years seems a perverse name for a variable containing that data.

Since that's a constant expression you should take the assignment
outside the loop.
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template->getElementsByTagName('subject-template')->item($i);

You used a foreach just a few lines up, how come you've forgotten it
so soon?

foreach my $item ($school_template-
getElementsByTagName('subject-template')

$subject_name = $item->getAttribute('name');

for my $count (0..4)
{
$periods = $item->getAttribute($years[$count]);

And again

foreach my $year (@years)
{
my $periods = $item->getAttribute($year);

return @template_subject_period;

You probably should not return the contents of
@template_subject_period (which could be big) but rather a reference
to @template_subject_period (which is just one value).
}

sub get_course_info
{
my $self = shift;
my $subject_name = shift;
my @years = shift;

You are storing a single argument in the array @years. What was it you
intended to do?
my $periods = shift;
my $count = shift;
my @template_subject_period = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);
for(my $i=0;$i <= $#template_subject_period;$i++)

Again with the C-style for!
{
print $#template_subject_period . "\n";
print "inside for loop\n";
if($template_subject_period[$i]->[1] eq $gotperiod)
{
push (@template_subject_period,
[$subject_name,$years[$count], $periods]);

print "Subject:\t" .
$template_subject_period[$i]->[0] . $template_subject_period[$i]->[2] . "\n";

}
}
return $self->{get_course_info};

You never put anything is $self->{get_course_info} execpt []. So
what's the point?

Sorry that subroutine is just too confused - I am unable to guess what
you were trying to do.

Here's what a cleaned up new() and load_school_template() might look
like but I can't help with get_course_info...

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}

sub load_school_template
{
my $self = shift;
my $parser = new XML::DOM::parser;

$self->{template_subject_period} = my $template_subject_period =
[];

my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");
my @years =
('periods_1','periods_2','periods_3','periods_4','periods_5');

foreach my $school_template($doc->getElementsByTagName('subject-
templates'))
{
foreach my $item ($school_template->getElementsByTagName('subject-
template')) {
my $subject_name = $item->getAttribute('name');
foreach my $year ( @years ) {
my $periods = $item->getAttribute($year);

push
@$template_subject_period,
[$subject_name,$year, $periods]);
}
}
return $template_subject_period;
}
 
K

king

=========================================================================
The below script if I am writing in a script its working fine but I
want to make this a module.

As the subroutine this (load_school_template ) will store the values
and

the get_course_info will display the values.
But I am not clear about the reference so I am using simple array that
is @template_subject_period. And by using the
same @template_subject_period array in the get_course_info subroutine
I am getting the output as name of the subject and number of periods
by giving input the no of years.

But inside the get_course_info method the @template_subject_period
value is not used.

My requirement is the get_course_info method should give out put as
the subject name and the no. of periods when
i will give input as "periods_1" or periods_2" etc..

this is the XML file from which I am getting the out put.name :
school.xml
===========================================================================
<?xml version="1.0" ?>
<school-template>
<class-templates>
<class-template marker="1" name="4 *" />
<class-template marker="2" name="5 *" />
<class-template marker="3" name="1 *" />
<class-template marker="4" name="2 *" />
<class-template marker="5" name="3 *" />
</class-templates>
<subject-templates>
<subject-template name="maths" periods_1="5" periods_2="5"
periods_3="4" periods_4="4" periods_5="4" />
<subject-template name="geography" periods_1="5" periods_2="5"
periods_3="4" periods_4="4" periods_5="4" />
<subject-template name="physics" periods_1="4" periods_2="4"
periods_3="3" periods_4="3" periods_5="3" />
<subject-template name="chemistry" periods_1="4" periods_2="4"
periods_3="-" periods_4="-" periods_5="-" />
<subject-template name="science" periods_1="2" periods_2="2"
periods_3="3" periods_4="3" periods_5="3" />
</subject-templates>
</school-template>

===========================================================================
this is the module i want to make: name: TPWizardMgr.pm
=======================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;


# load school types from config file
$self->{school_types} = [];
$self->load_config($CONFIG_FILE);
$self->{load_school_template} = [];
return $self;
}


sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
our @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
school.xml");

foreach my $school_template($doc-
getElementsByTagName('subject-templates'))
{
$len = $school_template-
getElementsByTagName('subject-template')->getLength() ;
@years =
('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template-
getElementsByTagName('subject-template')->item($i); $subject_name = $item-
getAttribute('name');
for my $count (0..4)
{
$periods = $item-
getAttribute($years[$count]);
push
(@template_subject_period, [$subject_name,$years[$count], $periods]);

}
}
}

$doc->dispose();
}

sub get_course_info
{
my $self = shift;
my $subject_name = shift;
my @years = shift;
my $periods = shift;
my $count = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);
for(my $i=0;$i <= $#template_subject_period;$i++)
{
#print $#template_subject_period . "\n";
print $#{$self->{load_school_template}. "\n";
print "inside for loop\n";
if($template_subject_period[$i]->[1] eq $gotperiod)
{
push (@template_subject_period, [$subject_name,
$years[$count], $periods]);
print "Subject:\t" .
$template_subject_period[$i]->[0] . $template_subject_period[$i]-
[2] . "\n";
}
}
return $self->{get_course_info};
}


1;


===========================================================================
injunjoel said:
Greetings,
Here are my suggestions based on what I understood from your post.
Read the comments at the bottom for more details.

==========================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# load school types from config file
$self->load_school_template();

#From the looks of it you don't need to call this
#when you create the object so leave it out.
#$self->get_course_info();

return $self;

}

sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc-
getElementsByTagName('subject-templates'))
{
$len = $school_template->getElementsByTagName('subject-
template')->getLength() ;

@years
=('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template-
getElementsByTagName('subject-template')->item($i);

$subject_name = $item->getAttribute('name');

for my $count (0..4)
{
$periods = $item-
getAttribute($years[$count]);

#you created a blessed hash for your object structure... USE
IT! #here we nest a bunch of stuff in the object hash
# $self->{'subject_period'} contains a hash with
# $subject_name as keys which contains a hash with
# @years as keys so 'periods_1','periods_2', etc...
# with a array of what ever came out of $periods
#
#this is all to facilitate your lookup in get_course_info();
push (@{$self->{'subject_period'}-
{$subject_name}->{$years[$count]}}, $periods);
}
}
}
return 1;
}

sub get_course_info
{

# This is now just a method of the underlying object hash
# call it with the subject name as the only argument


my $self = shift;
my $subject_name = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);

#lets check shall we?
if($gotperiod < 1 || $gotperiod > 5)
{
print "Period out of range.\nValid range is 1-5!\n";
return undef;
}

#standardize the periods key if they only entered a number.
$gotperiod = 'periods_'.$gotperiod if($gotperiod !~ /^periods_/);

#check if this is even a valid key/subject
if(exists($self->{'subject_period'}->{$subject_name}))
{
#do the lookup for this subject.
my @courses = @{$self->{'subject_period'}->{$subject_name}-
{$gotperiod}};

#print what we found from our lookup.
foreach my $course (@courses)
{
print "Subject:\t" . $subject_name . . "\n";
}
}
else {
print "Subject: $subject_name was not found!\n";
return undef;
}

return 1;
}

sub get_subject_names
{
$self = shift;
return sort {$a cmp $b} keys @{$self->{'subject_period'}};
}

1;


#
# sample usage:
# my $obj = TPWizardMgr->new();
# my @subjects = $obj->get_subject_names;
# foreach my $subject (@subjects)
# {
# $obj->get_course_info($subject);
# }
#
#
#
#


==========================================================================



I have a module named TPWizardMgr.pm as below.

========================================================================
package TPWizardMgr;
use strict;
use XML::DOM;

sub new
{
my $class = shift;
my $self = {};
bless $self, $class;

# reset all data
$self->{load_school_template} = {};
$self->{get_course_info} = {};

# load school types from config file
$self->{load_school_template} = [];
$self->{get_course_info} = [];

return $self;

}

sub load_school_template
{
my $self = shift;
my $len ;
my $item;
my @years;
my $periods;
my $subject_name;
my @template_subject_period;
my $parser = new XML::DOM::parser;
my $doc = $parser->parsefile ("/usr/local/apache2/wizard_data/
liceo_classico.xml");

foreach my $school_template($doc->getElementsByTagName('subject-templates'))

{
$len = $school_template->getElementsByTagName('subject-template')->getLength() ;

@years =
('periods_1','periods_2','periods_3','periods_4','periods_5');
for(my $i = 0;$i<$len;$i++)
{
$item = $school_template->getElementsByTagName('subject-template')->item($i);

$subject_name = $item->getAttribute('name');

for my $count (0..4)
{
$periods = $item->getAttribute($years[$count]);

push
(@template_subject_period, [$subject_name,$years[$count], $periods]);
}
}
}

return @template_subject_period;

}

sub get_course_info
{
my $self = shift;
my $subject_name = shift;
my @years = shift;
my $periods = shift;
my $count = shift;
my @template_subject_period = shift;
print "Please enter period to get subject and number of
periods \n";
my $gotperiod = <>;
chomp($gotperiod);
for(my $i=0;$i <= $#template_subject_period;$i++)
{
print $#template_subject_period . "\n";
print "inside for loop\n";
if($template_subject_period[$i]->[1] eq $gotperiod)
{
push (@template_subject_period,
[$subject_name,$years[$count], $periods]);

print "Subject:\t" .
$template_subject_period[$i]->[0] . $template_subject_period[$i]->[2] . "\n";

}
}
return $self->{get_course_info};

}

1;
==================================================================

But I want to use the variable @template_subject_period in the
subroutine get_course_info( ).

I am not able to use this @template_subject_period variable value in
the get_course_info subroutine.

How I can do this.

Thanks in advance.
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,054
Latest member
LucyCarper

Latest Threads

Top