For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > March 2005 > Module questions (perhaps a module creation mini-tutorial)









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 Module questions (perhaps a module creation mini-tutorial)
Peter Rabbitson

2005-03-25, 3:56 pm

Hello list,

I am trying to make my own modules for some tasks, and I am trying to grasp
the basics before I go any further. Here is a dumb test module that I wrote
just to see how things are done - it takes an array of 3 values and adds
them together, returning the values on request.

### 3-element-array-calc test module (CalcTest.pm)

package CalcTest;

use warnings;
use strict;

my @collect;

1;

sub new {

my $class = shift;

my $self = {};

@collect = (0,0,0);

bless $self, $class;

return $self;
}

sub add {

print (shift @_);

if ( (scalar @_) != 3) {
return undef;
}

my ($var0, $var1, $var2) = @_;

$collect[0] += $var0;
$collect[1] += $var1;
$collect[2] += $var2;

return 1;
}


sub result {

return @collect;
}


#### main perl program (test.pl)

use warnings;
use strict;

use CalcTest;

my $calc = CalcTest->new();

print "error\n\n" unless $calc->add (3, 4, 5);

print "error\n\n" unless $calc->add (1, 2, 3);

print join (' * ',$calc->result);
print "\n\n";

exit 0;

The thing works, however there are too many unclear issues.

1. Everytime I call one of the subroutines (methods I believe they are
called?) I get a hash in $_[0] with only one value - the string name of the
package I am calling. What defines the contents of this hash? Is it always
just this single value pair or there might be additional values? If yes -
what kind? (A reference towards *clear* documentation would be best).

2. The idea of blessing... I understand the idea, I don't understand the
reason. Why does bless need an empty hash intialized for it to bless it?
Isn't blessing completely symbolic? Or I actually might put something in
\%self ? If I do - what does this give me?

3. The usage of my in a package - here and there I see clues that 'my' does
behave differently when used in a module - is this true? Is it correct do
declare a package-wide @collect and have subroutines work on this
semi-global variable (global from the package point of view), so I can get
results that stack-up - the addition in the above example, or the
accumulation like in Text::CSV where you keep pushing data in, and then you
wrap a string... you probably see where I am going.

4. If I don't define an explicit return value for a sub - is it always undef
(like I would expect) or the package occasionally might decide to assign
something as a return value?


Btw, a disclaimer to cover my private body parts - I searched extensively
enough (imho) for a good tutorial on this subject and all the docs follow
same theoretical-bullshit-endeavor model without actual low level
explanation. As a matter of fact I would never be able to write
the above code correctly without looking at an actual source of a CPAN
module (Text::CSV to be exact).

Thank you.

Peter
Jeff 'japhy' Pinyan

2005-03-25, 8:55 pm

On Mar 25, Peter Rabbitson said:

> package CalcTest;
>
> use warnings;
> use strict;
>
> my @collect;


This is suspect. You shouldn't be using this array. You should be
storing data in your object.

> 1;


It's probably safer to put this at the very end of your module, just in
case you have other code (non-subroutine code) that could possibly return
false.

> sub new {
>
> my $class = shift;
>
> my $self = {};
>
> @collect = (0,0,0);
>
> bless $self, $class;
>
> return $self;
> }


How about :

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

Now instead of using an outside array, each object will have its OWN three
numbers.

> sub add {
>
> print (shift @_);


The first argument to ANY method is the class or object that invoked the
method. $_[0] is the object in this case.

> if ( (scalar @_) != 3) {
> return undef;
> }
>
> my ($var0, $var1, $var2) = @_;
>
> $collect[0] += $var0;
> $collect[1] += $var1;
> $collect[2] += $var2;
>
> return 1;
> }


How about :

sub add {
my $self = shift;
return unless @_ == 3;
$self->[0] += shift;
$self->[1] += shift;
$self->[2] += shift;
return 1;
}

That uses the object $self, which is an array reference, and adds one
argument to each element of @$self in turn.

> sub result {
>
> return @collect;
> }


Here, it'd be:

sub result {
my $self = shift;
return @$self;
}

> #### main perl program (test.pl)
>
> use warnings;
> use strict;
>
> use CalcTest;
>
> my $calc = CalcTest->new();
>
> print "error\n\n" unless $calc->add (3, 4, 5);
>
> print "error\n\n" unless $calc->add (1, 2, 3);
>
> print join (' * ',$calc->result);
> print "\n\n";
>
> exit 0;


The interface to the module hasn't changed at all, so the code above
should still work.

> 1. Everytime I call one of the subroutines (methods I believe they are
> called?) I get a hash in $_[0] with only one value - the string name of the
> package I am calling. What defines the contents of this hash? Is it always
> just this single value pair or there might be additional values? If yes -
> what kind? (A reference towards *clear* documentation would be best).


You were misunderstanding the output of printing the object. It printed
something like

CalcTest=HASH(0x....)

That's what an object looks like when you print it. Class=TYPE(ADDR).

You typically STORE information in the object. Your code was ignoring it
entirely. There was no need for your code to be "object-oriented" at all.

> 2. The idea of blessing... I understand the idea, I don't understand the
> reason. Why does bless need an empty hash intialized for it to bless it?
> Isn't blessing completely symbolic? Or I actually might put something in
> \%self ? If I do - what does this give me?


Blessing a reference tells Perl that the reference is now an object of a
specific class, and can invoke methods of that class with the $obj->method
syntax.

> 3. The usage of my in a package - here and there I see clues that 'my' does
> behave differently when used in a module - is this true? Is it correct do
> declare a package-wide @collect and have subroutines work on this
> semi-global variable (global from the package point of view), so I can get
> results that stack-up - the addition in the above example, or the
> accumulation like in Text::CSV where you keep pushing data in, and then you
> wrap a string... you probably see where I am going.


You were using @collect poorly. With your code, you couldn't have TWO
instances of a CalcTest. Any work the first instance did would be erased
when the second instance is created, and after that, both instances would
always return the same results.

> 4. If I don't define an explicit return value for a sub - is it always undef
> (like I would expect) or the package occasionally might decide to assign
> something as a return value?


If there is no explicit return value for a function, it returns the LAST
thing it evaluated.

As far as documentation goes, please read

perldoc perlboot

--
Jeff "japhy" Pinyan % How can we ever be the sold short or
RPI Acacia Brother #734 % the cheated, we who for every service
http://japhy.perlmonk.org/ % have long ago been overpaid?
http://www.perlmonks.org/ % -- Meister Eckhart
Sponsored Links







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

Copyright 2008 codecomments.com