Trying to understand a constructor with an array.

O

Overt

Don't anybody laugh. I am trying to learn Object Perl and modifying
examples in the books just to understand what is going on.

Here is a simple object creation where I am using an array rather than a
hash.

Called with this -
my @tarray;
$tarray[0][0] = 1;
$tarray[0][1] = 2;
$tarray[1][0] = 3;
$tarray[1][1] = 4;
my $displayobj = Display->new(\@tarray);

Here is the constructor -
sub new {
my $class = shift;
my $self = [];
$self->[@_] = shift;
bless($self, $class);
$DB::single = 1; #this is where I examine $self
return $self;
}

It works ok, but $self contains an array of an array, rather than just a 2
dimentional array. Like so
$self[0][0][0] = [1]
$self[0][0][1] = [2]
$self[0][1][0] = [3]
$self[0][1][1] = [4]

Why an array of an array, rather than just an array?

Again, this isn't a problem I am trying to fix, just something I am trying
to understand.

Thanx anybody
Overt
 
L

Leon Timmermans

Don't anybody laugh. I am trying to learn Object Perl and modifying
examples in the books just to understand what is going on.

Here is a simple object creation where I am using an array rather than a
hash.

Called with this -
my @tarray;
$tarray[0][0] = 1;
$tarray[0][1] = 2;
$tarray[1][0] = 3;
$tarray[1][1] = 4;
my $displayobj = Display->new(\@tarray);

How about

my $displayobj = Display->new([ [1, 2], [3, 4] ]);
$self->[@_] = shift;

This line doesn't make sense to me at all.
It works ok, but $self contains an array of an array, rather than just a
2 dimentional array. Like so
$self[0][0][0] = [1]
$self[0][0][1] = [2]
$self[0][1][0] = [3]
$self[0][1][1] = [4]

Why an array of an array, rather than just an array?

I think what you want to do is:

my $self = [ @{+shift} ];

Regards,

Leon Timmermans
 
X

xhoster

Overt said:
sub new {
my $class = shift;
my $self = [];
$self->[@_] = shift;
It works ok, but $self contains an array of an array, rather than just a
2 dimentional array. Like so
$self[0][0][0] = [1]
$self[0][0][1] = [2]
$self[0][1][0] = [3]
$self[0][1][1] = [4]

Surely not. $self->[0][0][0]=1;
Why an array of an array, rather than just an array?

new is called with @_ containing two things. Both of those things
get shifted off, leaving @_ with zero things. Array subscripts,
like the @_ in "$self->[@_]", are evaluated in scalar context, and in a
scalar context arrays yield the number of elements, which is zero. So your
code is equivalent to:

$self->[0] = shift;

(The reason you get 0 rather than 1 is that the right hand side of the
assignment is evaluated first, so by the time @_ is evaluated in scalar
context on the left hand side, it has already been shifted.)

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
P

Peter J. Holzer

Here is a simple object creation where I am using an array rather than a
hash.

Called with this -
my @tarray;
$tarray[0][0] = 1;
$tarray[0][1] = 2;
$tarray[1][0] = 3;
$tarray[1][1] = 4;
my $displayobj = Display->new(\@tarray);

How about

my $displayobj = Display->new([ [1, 2], [3, 4] ]);
$self->[@_] = shift;

This line doesn't make sense to me at all.

This is tricky: shift modifies @_, so is the length of @_, which is used
as an index, taken before or after the shift? We know that the length is
1 before and 0 after the shift, so that might be equivalent to

$self->[0] = shift;

or to

$self->[1] = shift;

or it might even be completely undefined. Apparently, the shift is
evaluated first, so it's equivalent to $self->[0] = shift; But if the OP
meant that he should have written it instead of relying on an
unspecified evaluation order, and anyway I doubt that he meant it. But I
wonder what the thought that this would do.

It works ok, but $self contains an array of an array, rather than just a
2 dimentional array. Like so
$self[0][0][0] = [1]
$self[0][0][1] = [2]
$self[0][1][0] = [3]
$self[0][1][1] = [4]

Why an array of an array, rather than just an array?

I think what you want to do is:

my $self = [ @{+shift} ];

Or

$self = shift;

which is subtly different.

hp
 
L

Leon Timmermans

But I wonder what the thought that this would do.

Yeah, that's what I meant.
Or

$self = shift;

which is subtly different.

Yeah, but personally I'd by wary of blessing anything I didn't create
myself, that can bite one in unexpected ways.

Leon Timmermans
 
M

Michael Carman

Overt said:
my $self = [ @{+shift} ];

I would not have discovered it on my own (at least for a long while),
because I can't find that construction in any of my documentation.

That's probably because it's not one construct but several written together:

* The [...] creates a reference to an anonymous array. This is what
gets assigned to $self.
* The @{...} is an array dereference.
* The shift() function removes and returns the first element from an
array. If no array is specified (and you're inside a subroutine) it
operates on @_.
* @_ is the array used to pass arguments to subs.
* The + is the unary sign operator. It forces the "shift" to be
interpreted as a function call instead of as a bareword. Without it
the expression would parse as the array @shift instead of as
@{ shift(@_) }

Personally, I wouldn't write it this way, because I think it's very
obscure. I would write

my $self = shift;

as Peter suggested. You could add a check for C<ref($self) eq 'ARRAY'>
if you share Leon's concern and want to ensure that the user didn't pass
in the wrong thing as an argument.
I am just a hobbyist programmer (so far), but where do you learn this
type of info?

The best way to learn is by doing. Keep programming and keep learning
new things as you go. I learned gobs of Perl by lurking in this
newsgroup. Read the docs. Read (good) books. Whenever you see something
new, try to understand it and think of how and where you might use it.
Go back to your old code and rewrite it as you learn new and better idioms.
I keep tripping across neat stuff like the above and wonder just how
many zillions of other good items that I will never learn and can't
use because I don't know they exist.

I don't know. I've been using Perl for more than a decade and I still
learn new things occasionally. There are some dusty corners that I've
never really had a reason to explore.
Possibly you went to a professional school to learn.

Some of the people here have had a formal education in computer science,
but I don't think many have had formal schooling in Perl. There are
training courses though, and many of the more prominent posters here
teach them.

-mjc
 
P

Peter J. Holzer

Overt said:
my $self = [ @{+shift} ];

I would not have discovered it on my own (at least for a long while),
because I can't find that construction in any of my documentation.

That's probably because it's not one construct but several written together:

* The [...] creates a reference to an anonymous array. This is what
gets assigned to $self.
* The @{...} is an array dereference.
* The shift() function removes and returns the first element from an
array. If no array is specified (and you're inside a subroutine) it
operates on @_.
* @_ is the array used to pass arguments to subs.
* The + is the unary sign operator. It forces the "shift" to be
interpreted as a function call instead of as a bareword. Without it
the expression would parse as the array @shift instead of as
@{ shift(@_) }

Personally, I wouldn't write it this way, because I think it's very
obscure. I would write

my $self = shift;

as Peter suggested.

So I did. But I've been very brief because I wanted to tease the OP into
trying to find out what the subtle difference is. Probably too brief - I
don't think I succeeded.

As a matter of style, I vastly prefer

sub new {
my ($class, $data) = @_;
...
}

over

sub new {
my $class = shift;
my $data = shift;
...
}

especially if the second shift would be hidden in a complex expression
and not be immediately visible to the reader (I sometimes do use shift
(or even pop) to deal with optional arguments).

So that constructor would become:

sub new {
my ($class, $data) = @_;

my $self = $data;
bless $self, $class;
return $self;
}

or, if I wanted to copy the elements of @$data to @$self (and avoid
accidentally blessing $data):

sub new {
my ($class, $data) = @_;

my $self = [ @$data ];
bless $self, $class;
return $self;
}


You could add a check for C<ref($self) eq 'ARRAY'>
if you share Leon's concern and want to ensure that the user didn't pass
in the wrong thing as an argument.

Yup. Since perl cannot check types at compile time it is often a good
idea to add such checks at run time.

hp
 
B

Ben Morrow

Quoth Overt said:
It is just my opinion, but complex expressions are for production code.
Tutorial examples of code should have one function per line so that the
learner can easily decode what the code is doing. The production programmer
can always pack the stuff together if wanted.

I would disagree here: production code should *also* be written as
clearly as possible. It is even more important in that case that the
code be comprehensible: at least when working through a tutorial you
have the luxury of spending as much time as you need figuring things
out.

OTOH, composing expressions doesn't necessarily make them more complex.
One of the problems with languages like C is that the code ends up so
spread out it's difficult to see the flow of the logic: you end up being
unable to see the wood for the trees.
Even with functions I am familiar with, I usually leave them broken apart
just so that months later I can tell at a glance what I was trying to do.

Good. You should always think about how the code will read to someone
coming to it for the first time.

Ben
 

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,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top