[9424] in Perl-Users-Digest
Perl-Users Digest, Issue: 3020 Volume: 8
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue Jun 30 14:07:35 1998
Date: Tue, 30 Jun 98 10:54:12 -0700
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Tue, 30 Jun 1998 Volume: 8 Number: 3020
Today's topics:
question about objects <rob@intr.net>
Re: question about objects (Charlie Stross)
Re: question about objects <jdf@pobox.com>
Re: question about objects <tchrist@mox.perl.com>
Re: question about objects <rob@NOSPAMintr.net>
Re: question about objects <rob@NOSPAMintr.net>
Re: question about objects <rob@NOSPAMintr.net>
Re: question about objects <rob@NOSPAMintr.net>
Re: question about objects (Charlie Stross)
Randomize number between -0.5 and 0.5 (Huang)
Re: Randomize number between -0.5 and 0.5 (Larry Rosler)
Re: Randomize number between -0.5 and 0.5 <rra@stanford.edu>
Digest Administrivia (Last modified: 8 Mar 97) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Mon, 29 Jun 1998 01:39:44 -0400
From: susurrus <rob@intr.net>
To: rob@intr.net
Subject: question about objects
Message-Id: <359728A0.6368D8C2@intr.net>
hi. :)
I'm trying to figure out object oriented programming in Perl (I'm using
5.x4_04, from Redhat's rpm package), and I'm about at wits end! I
figured, as a good personal exercise, I would code an object that can
take x ne 0,y ne 0 real coordinates, with a method "quadrant" that would
report which quadrant it is in. I know there are simpler ways of
achieving that goal -- which is why I figured it is a perfect
example/case to learn from.
I wrote this in 2 files. The .pm file just contains the package for the
object, and the .pl file tries to create 2 instances and call thier
methods. From what I've read, it looks pretty good -- nothing nasty or
tricky going on here. Unfortunately, I can't get it to work. :)
The error I get when I run what I figure looks pretty good is:
--begin--
[rob@ldarknesswithin perl]$ test.pl
Can't locate object method "quadrant" via package "X: 2, ref: INTEGER
Y: , ref:
" at ./test.pl line 10.
--end--
Which, it seems to me, is an indication that the reference to the object
instance is getting lost somewhere. (???)
here's my code:
test.pl
#--##--##--#
#!/bin/perl
require "./point.pm";
*P = "point::new";
$x = P(1, 2);
$y = P(-1, -2);
$quadrant = $x->quadrant; print "$quadrant\n";
$quadrant = $y->quadrant; print "$quadrant\n\n";
#--##--##--# end test.pl
point.pm
#--##--##--#
package point;
sub new{
my $self = shift;
my ($x, $y) = @_;
my ($refx, $refy, $return);
$refx = "INTEGER" if($x =~ /^\d+$|^0[xX][\da-fA-F]+$/);
$refy = "INTEGER" if($y =~ /^\d+$|^0[xX][\da-fA-F]+$/);
return "X: $x, ref: $refx\nY: $y, ref: $refy\n\n"
if( ( !@_ || ( ( $refx ne "INTEGER" ) || ( $refy ne "INTEGER"
) ) ) );
$return = bless { "x" => $x, "y" => $y }, $self;
return $return;
}
sub quadrant{
my $self = shift;
my ($field1, $field2, $quadrant);
$field1++ if($self->x > 0);
$field2++ if($self->y > 0);
$quadrant = 1 if($field1 && $field2);
$quadrant = 3 if((!$field1) && (!$field2));
$quadrant = 2 if($field2 && (!$field1));
$quadrant = 4 if($field1 && (!$field2));
return $quadrant;
}
1;
#--##--##--# end point.pm
------------------------------
Date: Mon, 29 Jun 1998 12:53:00 GMT
From: charlie@antipope.org (Charlie Stross)
Subject: Re: question about objects
Message-Id: <slrn6pf3h6.rfn.charlie@cs.ed.datacash.com>
In the name of Kibo the Compassionate, the Merciful,
on Mon, 29 Jun 1998 01:39:44 -0400,susurrus <rob@intr.net> implored:
>hi. :)
Same to you too ...
>I'm trying to figure out object oriented programming in Perl (I'm using
>5.x4_04, from Redhat's rpm package), and I'm about at wits end! I
>figured, as a good personal exercise, I would code an object that can
>take x ne 0,y ne 0 real coordinates, with a method "quadrant" that would
>report which quadrant it is in. I know there are simpler ways of
>achieving that goal -- which is why I figured it is a perfect
>example/case to learn from.
Good idea. See below ...
>The error I get when I run what I figure looks pretty good is:
>--begin--
>[rob@ldarknesswithin perl]$ test.pl
>Can't locate object method "quadrant" via package "X: 2, ref: INTEGER
>Y: , ref:
>
>" at ./test.pl line 10.
>--end--
>Which, it seems to me, is an indication that the reference to the object
>instance is getting lost somewhere. (???)
Yup.
>here's my code:
>
>test.pl
>#--##--##--#
>
>#!/bin/perl
>
>require "./point.pm";
You used require() instead of use() to load your module. Consequently
stuff you put in it shows up in the namespace point, as opposed to MAIN.
(I think you need to get hold of the Camel book and read chapters 4 and 5
before you go on.)
>*P = "point::new";
>
>$x = P(1, 2);
>$y = P(-1, -2);
I don't know what you're trying to assign a scalar string to a
typeglob for in here; either I'm being particularly stupid, or you're
attempting to use a glob as a symbolic reference?
>$quadrant = $x->quadrant; print "$quadrant\n";
>$quadrant = $y->quadrant; print "$quadrant\n\n";
Hmm. You're trying to keep the x and y coordinates as separate objects,
with methods defined in the point.pm package, aren't you? That doesn't
seem natural to me.
And this bit of code ...
>sub quadrant{
> my $self = shift;
> my ($field1, $field2, $quadrant);
>
> $field1++ if($self->x > 0);
> $field2++ if($self->y > 0);
... looks broken to me. When you're writing a module, the object (called
$self here) is a reference to an anonymous hash (although arrays or
scalars _can_ be used if you're particularly sick and twisted :) which
has been blessed into the appropriate class. The blessing lets Perl know
which namespace to look in for subroutines (methods) invoked on objects
of the given class. The thing you're dereferencing with the arrow, as in
$self->x, is interpreted as being the sub named x defined in whatever
package $self is blessed into (or one of its parents, if you're
inheriting methods from somewhere else). So you are invoking a sub
called x, with the parameter $self, in your version of quadrant() -- but
you haven't defined such a subroutine in your package. Perhaps you really
wanted $self->{x}?
I'd code 'em as fields within a single object with methods like this:
-- snip -- Point.pm
package Point;
sub new {
# create a point object -- simple, no initializers
my ($self) = {};
bless $self, "Point";
return $self;
}
sub x {
# set or get the X axis coordinate; return zero if coordinate is zero
# simple -- expects a scalar
my ($self) = shift @_;
if (@_) {
# return 0 if first arg is zero
if ($_[0] == 0) {
return 0 ;
} else {
$self->{x} = $_[0];
}
} else {
return $self->{x};
}
}
sub y {
# set or get the Y axis coordinate; return zero if coordinate is zero
# simple -- expects a scalar
my ($self) = shift @_;
if (@_) {
# return 0 if first arg is zero
if ($_[0] == 0) {
return 0 ;
} else {
$self->{y} = $_[0];
}
} else {
return $self->{y};
}
}
# for bonus points, re-write x() and y() as a single sub invoked via the
# autoloader (answer on P.298 of the Camel book, 2nd edn. first printing ;-)
sub quadrant {
# return the quadrant this point is in
my ($self) = shift @_;
if (($self->x() > 0) && ($self->y() > 0)) {
return 1;
} elsif (($self->x() < 0) && ($self->y() < 0)) {
return 3;
} elsif (($self->x() < 0) && ($self->y() > 0)) {
return 2;
} elsif (($self->x() > 0) && ($self->y() < 0)) {
return 4;
} else {
return 0; # eeek!
}
}
1;
-- snip -- test.pl
#!/bin/perl -- -*- perl -*-
#
# test driver program
#
use strict; # be a syntax fascist ;-)
use lib "."; # tell perl to search for modules in this directory first
use Point; # tell perl to use the module Point
my ($foo) = new Point; # create new point object
$foo->x(1);
$foo->y(2);
print "point(1,2) is in ", $foo->quadrant(), "\n";
$foo->x(-1);
$foo->y(-2);
print "point(-1,-2) is in ", $foo->quadrant(), "\n";
-- snip --
NB: Yes: this is verbose and bulky, and half those if statements could be
replaced by the ternary operator, and a version where new() accepts x,y
coordinates as an initializer would be shorter. But I'd like to think it's
also clear and readable. If it isn't, please tell me why.
-- Charlie
"One World. One Web. One Program."
-Microsoft promotional advertisement
"Ein Volk, ein Reich, ein Fuhrer!"
-Adolf Hitler
------------------------------
Date: 29 Jun 1998 08:25:16 -0500
From: Jonathan Feinberg <jdf@pobox.com>
To: susurrus <rob@intr.net>
Subject: Re: question about objects
Message-Id: <k960tk5f.fsf@mailhost.panix.com>
susurrus <rob@intr.net> writes:
> #!/bin/perl
You really want to start using -w, especially while learning some new
concept.
> require "./point.pm";
Better would be
use lib '.';
use point;
Better still would be to name the module and its package Point, with a
capital P, since then you won't generate warnings about barewords.
> *P = "point::new";
Yik-Jim-Su-Eyuhtick-Tim-Kwimmer. You've now made an alias to the
new() method in the point package, which would enable you to say
my $point = P();
and thereby get a new point object. Perhaps you mean
$P = point->new();
I'd strongly suggest that you read the following documents:
perltoot
perlobj
perlstyle
I hope this helps.
--
Jonathan Feinberg jdf@pobox.com Sunny Brooklyn, NY
http://pobox.com/~jdf/
------------------------------
Date: 29 Jun 1998 14:11:58 GMT
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: Re: question about objects
Message-Id: <6n87be$pdm$1@csnews.cs.colorado.edu>
[courtesy cc of this posting sent to cited author via email]
In comp.lang.perl.misc,
susurrus <rob@intr.net> writes:
:I'm trying to figure out object oriented programming in Perl (I'm using
:5.x4_04, from Redhat's rpm package), and I'm about at wits end! I
:figured, as a good personal exercise, I would code an object that can
:take x ne 0,y ne 0 real coordinates, with a method "quadrant" that would
:report which quadrant it is in. I know there are simpler ways of
:achieving that goal -- which is why I figured it is a perfect
:example/case to learn from.
:require "./point.pm";
:*P = "point::new";
Normally you would allow the module to do its own exporting
rather than forcing an import. For example,
use Point;
or
use Point qw(P);
:$x = P(1, 2);
:$y = P(-1, -2);
So now you are callling point::new(1,2). But this is not a normal
constructor. A normal constructor would be called as point->new(1,2),
which is really point::new("point", 1, 2). You are making a function
call not a method call. That's fine -- assuming the function knows to
deal with it. Yours didn't.
:package point;
We like upper case module names. And use statements.
:sub new{
: my $self = shift;
: my ($x, $y) = @_;
: my ($refx, $refy, $return);
:
: $refx = "INTEGER" if($x =~ /^\d+$|^0[xX][\da-fA-F]+$/);
: $refy = "INTEGER" if($y =~ /^\d+$|^0[xX][\da-fA-F]+$/);
: return "X: $x, ref: $refx\nY: $y, ref: $refy\n\n"
: if( ( !@_ || ( ( $refx ne "INTEGER" ) || ( $refy ne "INTEGER"
:) ) ) );
:
: $return = bless { "x" => $x, "y" => $y }, $self;
:
: return $return;
:}
This is remarkably complex. And wrong. Why are you
sometimes returning a string instead of
an object, that is, a blessed
reference? Why don't you just have this:
sub new {
my $class = shift;
my ($x, $y) = @_;
my $self = {
"x" => $x,
"y" => $y,
};
bless $self, $class;
return $self;
}
If you really want the P thing, you should use a proper exporter.
I think this is what you want:
sub P { __PACKAGE__->new(@_) }
:
:sub quadrant{
: my $self = shift;
: my ($field1, $field2, $quadrant);
:
: $field1++ if($self->x > 0);
: $field2++ if($self->y > 0);
You never declared a method called x or y. You don't get these
automatically if you're now using something like Class::Struct.
sub x { shift->{"x"} }
sub y { shift->{"y"} }
Would seem to suffice in this case. The general case likes things
like
sub x {
my $self = shift;
if (@_) {
$self->{"x"} = shift;
}
return $self->{"x"};
}
Or even
use Carp;
sub x {
my $self = shift;
if (@_) {
croak "too many arguments: @_" if @_ > 1;
my $n = shift;
croak "$n not numeric" unless $n =~ /pick something here/;
$self->{"x"} = $n;
}
return $self->{"x"};
}
--tom
--
"We stand on the shoulders of giants and kick
their ears whenever we feel like it." --Larry Wall
------------------------------
Date: Mon, 29 Jun 1998 18:44:40 -0400
From: Rob Collins <rob@NOSPAMintr.net>
To: charlie@NOSPAMintr.net, @, nospam@NOSPAMintr.net, .@NOSPAMintr.net, antipope@NOSPAMintr.net, org@NOSPAMintr.net
Subject: Re: question about objects
Message-Id: <359818D8.66555EAA@NOSPAMintr.net>
thanks. :)
Charlie Stross wrote:
> >here's my code:
> >
> >test.pl
> >#--##--##--#
> >
> >#!/bin/perl
> >
> >require "./point.pm";
>
> You used require() instead of use() to load your module. Consequently
> stuff you put in it shows up in the namespace point, as opposed to MAIN.
Ahh... that's why! I had originally written point like this;sub new { ...
}
*P = \&new;
And then, in the test.pl file, I would try;
require "./point.pm";
$x = P(1, 2);
I take it I could have successfully done it with the use statement(?). I tried
to get use to work, but I gave up cause I couldn't get it to behave (it couldn't
handle the parent directory part required to find the .pm file).
> (I think you need to get hold of the Camel book and read chapters 4 and 5
> before you go on.)
yeah, maybe, except that the chapters on objects in that book are very ambiguous
and not very good (IMHO), so instead I got the Advanced Perl Programming book
and the sections on objects are much clearer (obviously not enough though)!
> >*P = "point::new";
> >
> >$x = P(1, 2);
> >$y = P(-1, -2);
>
> I don't know what you're trying to assign a scalar string to a
> typeglob for in here; either I'm being particularly stupid, or you're
> attempting to use a glob as a symbolic reference?
I'm trying to get the look and feel of my object right. I want to use it "$x =
P($a, $b);", because of the simularity to Cartesean (can't spell) notation.
>From your suggestion above I take it when I get home tonight I can put the .pm
file in the search path and use the use() statement, and the *P = "point::new";
bit won't be necessary (on the test.pl side, on the use side, I'll use
*P=\&new;) at all.
> >$quadrant = $x->quadrant; print "$quadrant\n";
> >$quadrant = $y->quadrant; print "$quadrant\n\n";
>
> Hmm. You're trying to keep the x and y coordinates as separate objects,
> with methods defined in the point.pm package, aren't you? That doesn't
> seem natural to me.
No, I think you misunderstand. P(a,b) defines a point. $x = P(a, b). $y is a
totally different point. If I wanted to do that, I would have coded two
objects, and only passed one value to each. sub quadrant is just a function to
fulfill another aspect of graphing a point along a plane (to define an x-axis
and a y-axis, you get 4 quadrants on the plane -- the sub just tells you what
quadrant you are in).
> I'd code 'em as fields within a single object with methods like this:
When I get home tonight I'll look into your puzzle and play with this a while.
Thank you for all the help.
> -- snip -- Point.pm
>
> package Point;
>
> sub new {
> # create a point object -- simple, no initializers
> my ($self) = {};
> bless $self, "Point";
> return $self;
> }
>
> sub x {
> # set or get the X axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{x} = $_[0];
> }
> } else {
> return $self->{x};
> }
> }
>
> sub y {
> # set or get the Y axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{y} = $_[0];
> }
> } else {
> return $self->{y};
> }
> }
>
> # for bonus points, re-write x() and y() as a single sub invoked via the
> # autoloader (answer on P.298 of the Camel book, 2nd edn. first printing ;-)
>
> sub quadrant {
> # return the quadrant this point is in
> my ($self) = shift @_;
> if (($self->x() > 0) && ($self->y() > 0)) {
> return 1;
> } elsif (($self->x() < 0) && ($self->y() < 0)) {
> return 3;
> } elsif (($self->x() < 0) && ($self->y() > 0)) {
> return 2;
> } elsif (($self->x() > 0) && ($self->y() < 0)) {
> return 4;
> } else {
> return 0; # eeek!
> }
> }
>
> 1;
>
> -- snip -- test.pl
>
> #!/bin/perl -- -*- perl -*-
> #
> # test driver program
> #
> use strict; # be a syntax fascist ;-)
> use lib "."; # tell perl to search for modules in this directory first
> use Point; # tell perl to use the module Point
>
> my ($foo) = new Point; # create new point object
>
> $foo->x(1);
> $foo->y(2);
> print "point(1,2) is in ", $foo->quadrant(), "\n";
>
> $foo->x(-1);
> $foo->y(-2);
> print "point(-1,-2) is in ", $foo->quadrant(), "\n";
>
> -- snip --
>
> NB: Yes: this is verbose and bulky, and half those if statements could be
> replaced by the ternary operator, and a version where new() accepts x,y
> coordinates as an initializer would be shorter. But I'd like to think it's
> also clear and readable. If it isn't, please tell me why.
>
> -- Charlie
>
> "One World. One Web. One Program."
> -Microsoft promotional advertisement
> "Ein Volk, ein Reich, ein Fuhrer!"
> -Adolf Hitler
------------------------------
Date: Mon, 29 Jun 1998 18:45:18 -0400
From: Rob Collins <rob@NOSPAMintr.net>
To: charlie@NOSPAMintr.net, @, nospam@NOSPAMintr.net, .@NOSPAMintr.net, antipope@NOSPAMintr.net, org@NOSPAMintr.net
Subject: Re: question about objects
Message-Id: <359818FE.77F914C1@NOSPAMintr.net>
thanks. :)
Charlie Stross wrote:
> >here's my code:
> >
> >test.pl
> >#--##--##--#
> >
> >#!/bin/perl
> >
> >require "./point.pm";
>
> You used require() instead of use() to load your module. Consequently
> stuff you put in it shows up in the namespace point, as opposed to MAIN.
Ahh... that's why! I had originally written point like this;sub new { ...
}
*P = \&new;
And then, in the test.pl file, I would try;
require "./point.pm";
$x = P(1, 2);
I take it I could have successfully done it with the use statement(?). I tried
to get use to work, but I gave up cause I couldn't get it to behave (it couldn't
handle the parent directory part required to find the .pm file).
> (I think you need to get hold of the Camel book and read chapters 4 and 5
> before you go on.)
yeah, maybe, except that the chapters on objects in that book are very ambiguous
and not very good (IMHO), so instead I got the Advanced Perl Programming book
and the sections on objects are much clearer (obviously not enough though)!
> >*P = "point::new";
> >
> >$x = P(1, 2);
> >$y = P(-1, -2);
>
> I don't know what you're trying to assign a scalar string to a
> typeglob for in here; either I'm being particularly stupid, or you're
> attempting to use a glob as a symbolic reference?
I'm trying to get the look and feel of my object right. I want to use it "$x =
P($a, $b);", because of the simularity to Cartesean (can't spell) notation.
>From your suggestion above I take it when I get home tonight I can put the .pm
file in the search path and use the use() statement, and the *P = "point::new";
bit won't be necessary (on the test.pl side, on the use side, I'll use
*P=\&new;) at all.
> >$quadrant = $x->quadrant; print "$quadrant\n";
> >$quadrant = $y->quadrant; print "$quadrant\n\n";
>
> Hmm. You're trying to keep the x and y coordinates as separate objects,
> with methods defined in the point.pm package, aren't you? That doesn't
> seem natural to me.
No, I think you misunderstand. P(a,b) defines a point. $x = P(a, b). $y is a
totally different point. If I wanted to do that, I would have coded two
objects, and only passed one value to each. sub quadrant is just a function to
fulfill another aspect of graphing a point along a plane (to define an x-axis
and a y-axis, you get 4 quadrants on the plane -- the sub just tells you what
quadrant you are in).
> I'd code 'em as fields within a single object with methods like this:
When I get home tonight I'll look into your puzzle and play with this a while.
Thank you for all the help.
>
>
> -- snip -- Point.pm
>
> package Point;
>
> sub new {
> # create a point object -- simple, no initializers
> my ($self) = {};
> bless $self, "Point";
> return $self;
> }
>
> sub x {
> # set or get the X axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{x} = $_[0];
> }
> } else {
> return $self->{x};
> }
> }
>
> sub y {
> # set or get the Y axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{y} = $_[0];
> }
> } else {
> return $self->{y};
> }
> }
>
> # for bonus points, re-write x() and y() as a single sub invoked via the
> # autoloader (answer on P.298 of the Camel book, 2nd edn. first printing ;-)
>
> sub quadrant {
> # return the quadrant this point is in
> my ($self) = shift @_;
> if (($self->x() > 0) && ($self->y() > 0)) {
> return 1;
> } elsif (($self->x() < 0) && ($self->y() < 0)) {
> return 3;
> } elsif (($self->x() < 0) && ($self->y() > 0)) {
> return 2;
> } elsif (($self->x() > 0) && ($self->y() < 0)) {
> return 4;
> } else {
> return 0; # eeek!
> }
> }
>
> 1;
>
> -- snip -- test.pl
>
> #!/bin/perl -- -*- perl -*-
> #
> # test driver program
> #
> use strict; # be a syntax fascist ;-)
> use lib "."; # tell perl to search for modules in this directory first
> use Point; # tell perl to use the module Point
>
> my ($foo) = new Point; # create new point object
>
> $foo->x(1);
> $foo->y(2);
> print "point(1,2) is in ", $foo->quadrant(), "\n";
>
> $foo->x(-1);
> $foo->y(-2);
> print "point(-1,-2) is in ", $foo->quadrant(), "\n";
>
> -- snip --
>
> NB: Yes: this is verbose and bulky, and half those if statements could be
> replaced by the ternary operator, and a version where new() accepts x,y
> coordinates as an initializer would be shorter. But I'd like to think it's
> also clear and readable. If it isn't, please tell me why.
>
> -- Charlie
>
> "One World. One Web. One Program."
> -Microsoft promotional advertisement
> "Ein Volk, ein Reich, ein Fuhrer!"
> -Adolf Hitler
------------------------------
Date: Mon, 29 Jun 1998 18:45:02 -0400
From: Rob Collins <rob@NOSPAMintr.net>
To: charlie@NOSPAMintr.net, @, nospam@NOSPAMintr.net, .@NOSPAMintr.net, antipope@NOSPAMintr.net, org@NOSPAMintr.net, rob@intr.net
Subject: Re: question about objects
Message-Id: <359818EE.A559139C@NOSPAMintr.net>
thanks. :)
Charlie Stross wrote:
> >here's my code:
> >
> >test.pl
> >#--##--##--#
> >
> >#!/bin/perl
> >
> >require "./point.pm";
>
> You used require() instead of use() to load your module. Consequently
> stuff you put in it shows up in the namespace point, as opposed to MAIN.
Ahh... that's why! I had originally written point like this;sub new { ...
}
*P = \&new;
And then, in the test.pl file, I would try;
require "./point.pm";
$x = P(1, 2);
I take it I could have successfully done it with the use statement(?). I tried
to get use to work, but I gave up cause I couldn't get it to behave (it couldn't
handle the parent directory part required to find the .pm file).
> (I think you need to get hold of the Camel book and read chapters 4 and 5
> before you go on.)
yeah, maybe, except that the chapters on objects in that book are very ambiguous
and not very good (IMHO), so instead I got the Advanced Perl Programming book
and the sections on objects are much clearer (obviously not enough though)!
> >*P = "point::new";
> >
> >$x = P(1, 2);
> >$y = P(-1, -2);
>
> I don't know what you're trying to assign a scalar string to a
> typeglob for in here; either I'm being particularly stupid, or you're
> attempting to use a glob as a symbolic reference?
I'm trying to get the look and feel of my object right. I want to use it "$x =
P($a, $b);", because of the simularity to Cartesean (can't spell) notation.
>From your suggestion above I take it when I get home tonight I can put the .pm
file in the search path and use the use() statement, and the *P = "point::new";
bit won't be necessary (on the test.pl side, on the use side, I'll use
*P=\&new;) at all.
> >$quadrant = $x->quadrant; print "$quadrant\n";
> >$quadrant = $y->quadrant; print "$quadrant\n\n";
>
> Hmm. You're trying to keep the x and y coordinates as separate objects,
> with methods defined in the point.pm package, aren't you? That doesn't
> seem natural to me.
No, I think you misunderstand. P(a,b) defines a point. $x = P(a, b). $y is a
totally different point. If I wanted to do that, I would have coded two
objects, and only passed one value to each. sub quadrant is just a function to
fulfill another aspect of graphing a point along a plane (to define an x-axis
and a y-axis, you get 4 quadrants on the plane -- the sub just tells you what
quadrant you are in).
> I'd code 'em as fields within a single object with methods like this:
When I get home tonight I'll look into your puzzle and play with this a while.
Thank you for all the help.
>
>
> -- snip -- Point.pm
>
> package Point;
>
> sub new {
> # create a point object -- simple, no initializers
> my ($self) = {};
> bless $self, "Point";
> return $self;
> }
>
> sub x {
> # set or get the X axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{x} = $_[0];
> }
> } else {
> return $self->{x};
> }
> }
>
> sub y {
> # set or get the Y axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{y} = $_[0];
> }
> } else {
> return $self->{y};
> }
> }
>
> # for bonus points, re-write x() and y() as a single sub invoked via the
> # autoloader (answer on P.298 of the Camel book, 2nd edn. first printing ;-)
>
> sub quadrant {
> # return the quadrant this point is in
> my ($self) = shift @_;
> if (($self->x() > 0) && ($self->y() > 0)) {
> return 1;
> } elsif (($self->x() < 0) && ($self->y() < 0)) {
> return 3;
> } elsif (($self->x() < 0) && ($self->y() > 0)) {
> return 2;
> } elsif (($self->x() > 0) && ($self->y() < 0)) {
> return 4;
> } else {
> return 0; # eeek!
> }
> }
>
> 1;
>
> -- snip -- test.pl
>
> #!/bin/perl -- -*- perl -*-
> #
> # test driver program
> #
> use strict; # be a syntax fascist ;-)
> use lib "."; # tell perl to search for modules in this directory first
> use Point; # tell perl to use the module Point
>
> my ($foo) = new Point; # create new point object
>
> $foo->x(1);
> $foo->y(2);
> print "point(1,2) is in ", $foo->quadrant(), "\n";
>
> $foo->x(-1);
> $foo->y(-2);
> print "point(-1,-2) is in ", $foo->quadrant(), "\n";
>
> -- snip --
>
> NB: Yes: this is verbose and bulky, and half those if statements could be
> replaced by the ternary operator, and a version where new() accepts x,y
> coordinates as an initializer would be shorter. But I'd like to think it's
> also clear and readable. If it isn't, please tell me why.
>
> -- Charlie
>
> "One World. One Web. One Program."
> -Microsoft promotional advertisement
> "Ein Volk, ein Reich, ein Fuhrer!"
> -Adolf Hitler
------------------------------
Date: Mon, 29 Jun 1998 18:46:35 -0400
From: Rob Collins <rob@NOSPAMintr.net>
To: rob@intr.net
Subject: Re: question about objects
Message-Id: <3598194B.17A67426@NOSPAMintr.net>
thanks. :)
Charlie Stross wrote:
> >here's my code:
> >
> >test.pl
> >#--##--##--#
> >
> >#!/bin/perl
> >
> >require "./point.pm";
>
> You used require() instead of use() to load your module. Consequently
> stuff you put in it shows up in the namespace point, as opposed to MAIN.
Ahh... that's why! I had originally written point like this;sub new { ...
}
*P = \&new;
And then, in the test.pl file, I would try;
require "./point.pm";
$x = P(1, 2);
I take it I could have successfully done it with the use statement(?). I tried
to get use to work, but I gave up cause I couldn't get it to behave (it couldn't
handle the parent directory part required to find the .pm file).
> (I think you need to get hold of the Camel book and read chapters 4 and 5
> before you go on.)
yeah, maybe, except that the chapters on objects in that book are very ambiguous
and not very good (IMHO), so instead I got the Advanced Perl Programming book
and the sections on objects are much clearer (obviously not enough though)!
> >*P = "point::new";
> >
> >$x = P(1, 2);
> >$y = P(-1, -2);
>
> I don't know what you're trying to assign a scalar string to a
> typeglob for in here; either I'm being particularly stupid, or you're
> attempting to use a glob as a symbolic reference?
I'm trying to get the look and feel of my object right. I want to use it "$x =
P($a, $b);", because of the simularity to Cartesean (can't spell) notation.
>From your suggestion above I take it when I get home tonight I can put the .pm
file in the search path and use the use() statement, and the *P = "point::new";
bit won't be necessary (on the test.pl side, on the use side, I'll use
*P=\&new;) at all.
> >$quadrant = $x->quadrant; print "$quadrant\n";
> >$quadrant = $y->quadrant; print "$quadrant\n\n";
>
> Hmm. You're trying to keep the x and y coordinates as separate objects,
> with methods defined in the point.pm package, aren't you? That doesn't
> seem natural to me.
No, I think you misunderstand. P(a,b) defines a point. $x = P(a, b). $y is a
totally different point. If I wanted to do that, I would have coded two
objects, and only passed one value to each. sub quadrant is just a function to
fulfill another aspect of graphing a point along a plane (to define an x-axis
and a y-axis, you get 4 quadrants on the plane -- the sub just tells you what
quadrant you are in).
> I'd code 'em as fields within a single object with methods like this:
When I get home tonight I'll look into your puzzle and play with this a while.
Thank you for all the help.
>
>
> -- snip -- Point.pm
>
> package Point;
>
> sub new {
> # create a point object -- simple, no initializers
> my ($self) = {};
> bless $self, "Point";
> return $self;
> }
>
> sub x {
> # set or get the X axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{x} = $_[0];
> }
> } else {
> return $self->{x};
> }
> }
>
> sub y {
> # set or get the Y axis coordinate; return zero if coordinate is zero
> # simple -- expects a scalar
> my ($self) = shift @_;
> if (@_) {
> # return 0 if first arg is zero
> if ($_[0] == 0) {
> return 0 ;
> } else {
> $self->{y} = $_[0];
> }
> } else {
> return $self->{y};
> }
> }
>
> # for bonus points, re-write x() and y() as a single sub invoked via the
> # autoloader (answer on P.298 of the Camel book, 2nd edn. first printing ;-)
>
> sub quadrant {
> # return the quadrant this point is in
> my ($self) = shift @_;
> if (($self->x() > 0) && ($self->y() > 0)) {
> return 1;
> } elsif (($self->x() < 0) && ($self->y() < 0)) {
> return 3;
> } elsif (($self->x() < 0) && ($self->y() > 0)) {
> return 2;
> } elsif (($self->x() > 0) && ($self->y() < 0)) {
> return 4;
> } else {
> return 0; # eeek!
> }
> }
>
> 1;
>
> -- snip -- test.pl
>
> #!/bin/perl -- -*- perl -*-
> #
> # test driver program
> #
> use strict; # be a syntax fascist ;-)
> use lib "."; # tell perl to search for modules in this directory first
> use Point; # tell perl to use the module Point
>
> my ($foo) = new Point; # create new point object
>
> $foo->x(1);
> $foo->y(2);
> print "point(1,2) is in ", $foo->quadrant(), "\n";
>
> $foo->x(-1);
> $foo->y(-2);
> print "point(-1,-2) is in ", $foo->quadrant(), "\n";
>
> -- snip --
>
> NB: Yes: this is verbose and bulky, and half those if statements could be
> replaced by the ternary operator, and a version where new() accepts x,y
> coordinates as an initializer would be shorter. But I'd like to think it's
> also clear and readable. If it isn't, please tell me why.
>
> -- Charlie
>
> "One World. One Web. One Program."
> -Microsoft promotional advertisement
> "Ein Volk, ein Reich, ein Fuhrer!"
> -Adolf Hitler
------------------------------
Date: Tue, 30 Jun 1998 08:27:57 GMT
From: charlie@antipope.org (Charlie Stross)
Subject: Re: question about objects
Message-Id: <slrn6ph8ct.23c.charlie@cs.ed.datacash.com>
[NB: Please be careful when using Netscape to post news -- four or five
copies of this posting have shown up here already! Just hit the button
once, please, and don't worry if it doesn't show up immediately.]
In the name of Kibo the Compassionate, the Merciful,
on Mon, 29 Jun 1998 18:44:40 -0400,Rob Collins
the supplicant <rob@NOSPAMintr.net> implored:
>>
>> I don't know what you're trying to assign a scalar string to a
>> typeglob for in here; either I'm being particularly stupid, or you're
>> attempting to use a glob as a symbolic reference?
>
>I'm trying to get the look and feel of my object right. I want to use it "$x =
>P($a, $b);", because of the simularity to Cartesean (can't spell) notation.
Okay. Then what you want to do is define a sub called P (in the Point.pm
package) which accepts two parameters (x and y) and returns a new object
of type Point. (Basically it's the new() method by any other name, with
initialisers.) This is easy to code, although I'd be a bit leery of it --
it plays fast and loose with the usual perl OOP conventions.
sub P ($$) {
my ($self) = { "x" => shift @_,
"y" => shift @_ };
return bless $self, "Point";
}
Of course, to use this you need to say something like:
my ($foo) = Point::P($x, $y);
print "foo's quadrant is ", $foo->quadrant(), "\n";
If you want to avoid having to refer to the namespace Point:: you need
to investigate the Exporter.
>From your suggestion above I take it when I get home tonight I can put the .pm
>file in the search path and use the use() statement, and the *P = "point::new";
>bit won't be necessary (on the test.pl side, on the use side, I'll use
>*P=\&new;) at all.
You can try. (I think your original code needs some more changes, though --
I found it rather reluctant to run :)
>> >$quadrant = $x->quadrant; print "$quadrant\n";
>> >$quadrant = $y->quadrant; print "$quadrant\n\n";
>>
>> Hmm. You're trying to keep the x and y coordinates as separate objects,
>> with methods defined in the point.pm package, aren't you? That doesn't
>> seem natural to me.
>
>No, I think you misunderstand. P(a,b) defines a point. $x = P(a, b). $y is a
>totally different point.
Right. My confusion: I thought they were meant to be X and Y coordinates.
(Would you mind using slightly less ambiguous variable names in future,
when asking for help? In any other context it wouldn't be a problem, but ...)
-- Charlie
"Computers depreciate faster than you expect, even when you take
Charlie's Depreciation Hypothesis into account"
-- Charlie's Depreciation Hypothesis
------------------------------
Date: Mon, 29 Jun 1998 14:56:04 GMT
From: wong2020@tm.net.my (Huang)
Subject: Randomize number between -0.5 and 0.5
Message-Id: <3597aa9e.1090026@news.tm.net.my>
Hi:
I have wrote the segments of codes to randomized number between 0
and 0.1
What I wish to accomplish is between -0.5 and 0.5. Can you help me
on this? Thanks.
$randnum = ( rand (1));
if ($randnum >=0.1) {
$randnum = ($randnum)/10;}
------------------------------
Date: Mon, 29 Jun 1998 08:25:38 -0700
From: lr@hpl.hp.com (Larry Rosler)
Subject: Re: Randomize number between -0.5 and 0.5
Message-Id: <MPG.100151161697894c989701@nntp.hpl.hp.com>
In article <3597aa9e.1090026@news.tm.net.my> on Mon, 29 Jun 1998 14:56:04
GMT, Huang <wong2020@tm.net.my> says...
> Hi:
>
> I have wrote the segments of codes to randomized number between 0
> and 0.1
>
> What I wish to accomplish is between -0.5 and 0.5. Can you help me
> on this? Thanks.
>
> $randnum = ( rand (1));
> if ($randnum >=0.1) {
> $randnum = ($randnum)/10;}
For this, why not just use rand(0.1) ?
And for your question, rand(1) - 0.5 ?
--
Larry Rosler
Hewlett-Packard Laboratories
http://www.hpl.hp.com/personal/Larry_Rosler/
lr@hpl.hp.com
------------------------------
Date: 29 Jun 1998 08:33:49 -0700
From: Russ Allbery <rra@stanford.edu>
Subject: Re: Randomize number between -0.5 and 0.5
Message-Id: <m3wwa0mdcy.fsf@windlord.Stanford.EDU>
In comp.lang.perl.misc, Huang <wong2020@tm.net.my> writes:
> I have wrote the segments of codes to randomized number between 0 and
> 0.1
> What I wish to accomplish is between -0.5 and 0.5. Can you help me on
> this? Thanks.
> $randnum = ( rand (1));
> if ($randnum >=0.1) {
> $randnum = ($randnum)/10;}
Why not just use:
rand (1) - 0.5
?
--
#!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker
$^=q;@!>~|{>krw>yn{u<$$<[~||<Juukn{=,<S~|}<Jwx}qn{<Yn{u<Qjltn{ > 0gFzD gD,
00Fz, 0,,( 0hF 0g)F/=, 0> "L$/GEIFewe{,$/ 0C$~> "@=,m,|,(e 0.), 01,pnn,y{
rw} >;,$0=q,$,,($_=$^)=~y,$/ C-~><@=\n\r,-~$:-u/ #y,d,s,(\$.),$1,gee,print
------------------------------
Date: 8 Mar 97 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 8 Mar 97)
Message-Id: <null>
Administrivia:
The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc. For subscription or unsubscription requests, send
the single line:
subscribe perl-users
or:
unsubscribe perl-users
to almanac@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.
The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.
The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.
For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V8 Issue 3020
**************************************