Trying to understand a constructor with an array.

Discussion in 'Perl Misc' started by Overt, Aug 7, 2008.

  1. Overt

    Overt Guest

    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
     
    Overt, Aug 7, 2008
    #1
    1. Advertising

  2. On Thu, 07 Aug 2008 17:59:56 +0200, Overt wrote:

    > 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
     
    Leon Timmermans, Aug 7, 2008
    #2
    1. Advertising

  3. Overt

    Guest

    Overt <> wrote:
    > 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.
     
    , Aug 7, 2008
    #3
  4. On 2008-08-07 16:34, Leon Timmermans <> wrote:
    > On Thu, 07 Aug 2008 17:59:56 +0200, Overt wrote:
    >
    >> 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
     
    Peter J. Holzer, Aug 7, 2008
    #4
  5. On Thu, 07 Aug 2008 20:36:28 +0200, Peter J. Holzer wrote:

    > On 2008-08-07 16:34, Leon Timmermans <> wrote:
    > 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
     
    Leon Timmermans, Aug 7, 2008
    #5
  6. Overt wrote:
    >>
    >> 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
     
    Michael Carman, Aug 9, 2008
    #6
  7. On 2008-08-09 03:32, Michael Carman <> wrote:
    > Overt wrote:
    >>> 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
     
    Peter J. Holzer, Aug 11, 2008
    #7
  8. Overt

    Ben Morrow Guest

    Quoth Overt <>:
    >
    > 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

    --
    It will be seen that the Erwhonians are a meek and long-suffering people,
    easily led by the nose, and quick to offer up common sense at the shrine of
    logic, when a philosopher convinces them that their institutions are not based
    on the strictest morality. [Samuel Butler, paraphrased]
     
    Ben Morrow, Aug 12, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul K

    Trying to understand...

    Paul K, Nov 19, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    356
    Paul K
    Nov 19, 2003
  2. =?Utf-8?B?QmlsbCBCb3Jn?=

    Trying to understand ticket/cookie expiration

    =?Utf-8?B?QmlsbCBCb3Jn?=, Oct 8, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    362
    =?Utf-8?B?QmlsbCBCb3Jn?=
    Oct 8, 2004
  3. neo
    Replies:
    4
    Views:
    325
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,281
  5. Sreenivas

    dont understand constructor...

    Sreenivas, Dec 20, 2007, in forum: Java
    Replies:
    7
    Views:
    321
Loading...

Share This Page