1

I'm creating a new object like this:

TestObject->new(@array1, @array2)

My new method looks like this:

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

  my $self->{Array1} = shift;
  my $self->{Array2} = shift;

  bless($self, $class);

  return $self;
}

As a simple test to access the data, I'm trying this, and then once I get it working, I can build more meaningful logic:

sub mymethod {
  my $self = shift;
  my $param = shift;

  my $array1Value = shift(my $self->{Array1});
  my $array2Value = shift(my $self->{Array2});

  print $array1Value." ".$array2Value;
}

But when I call mymethod, I get this error:

Type of arg 1 to shift must be array (not hash element) at Tests/MyObject.pm line 21, near "})"

Suggestions? I read this page on Perl data structures, but they don't have examples for creating a hash of arrays using arguments to a method using shift. So my problem might be there.

1
  • 1
    What exactly is this? shift(my $self->{Array1}) Commented Nov 16, 2009 at 15:16

4 Answers 4

5

When you pass arrays as parameters, they are flattened. You can pass references to them. See perlsub

#!/usr/bin/env perl

package foo;

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

    $self->{Array1} = shift;
    $self->{Array2} = shift;

    bless($self, $class);

    return $self;
}

sub mymethod {
  my $self = shift;
  my $param = shift;

  my $array1Value = shift( @{$self->{Array1}} );
  my $array2Value = shift( @{$self->{Array2}} );

  print "$array1Value $array2Value\n";
}

package main;

my @a = ( 0, 1, 2);
my @b = ( 3, 4, 5);
my $o = new foo( \@a, \@b );;
$o->mymethod;
Sign up to request clarification or add additional context in comments.

3 Comments

Minor nit: Do not use indirect object syntax in Perl (new Foo as opposed to the better Foo->new). Cf. perldoc.perl.org/perlobj.html#Indirect-Object-Syntax
Don't use all lowercase package names either.
4

you have to use pointers to arrays, not arrays in this case:

  TestObject->new([@array1], [@array2])

and then later

my $array1Value = shift(@{$self->{Array1}});

5 Comments

new(\@array1, \@array2) will be much more efficient since [@foo] creates a new anonymous array and then (shallowly) copies the elements of @foo into that whereas \@foo creates a reference to the existing array. Also note that in Perl, we generally refer to this as a reference, not as a pointer. There are no C-like pointers in Perl.
this is exactly because I am generally using [] syntax instead of \@. The object is supposed to encapsulate data; it can not be responsible for whatever happens to those arrays outside of its context. The question of efficiency IMO will be raised only in rare cases where we have to handle HUGE volumes of data and fine-tune data copying
catwalk: then you may want a deep copy (e.g. Storable::dclone); [@foo] will copy the values in @foo, but the new array will still be connected to the values accessible from the old if the values are themselves references.
[replacing previous, completely wrong-headed comment:] The encapsulation problem should be relegated to the callee, actually. Let the caller use whatever he wants; if you want to be insulated to changes in the arguments, make the copy in the callee.
You guys have just come up with a very common test case: pass some data to a method and then alter that data in the caller; does the object's version of the data also get altered? It's surprising how often this is overlooked!
1

You're shifting an arrayref instead of an actual array.

The syntax ytou're probably looking for is:

my $array1Value = shift @{ $self->{Array1} };
my $array2Value = shift @{ $self->{Array2} };

Note how the array is dereferenced using @.

2 Comments

Also beware that this will be modifying the original array, not a copy of it.
I supposed that's what he wants, as he's using shift instead of subscripting, but it's still worth mentioning. +1
0

you need to derefernece the array ref:

@{$self->{Array2}}

By the way if you are using OO I emphatically suggest you look into Moose. It will make your life much easier!

3 Comments

I think you'd need to reference it in the first place though too, right? Like ->new(\@array1, \@array2)?
That worked. When I tried that, I just tried @$self->{Array2}, forgetting the { and } around $self->{Array2}.
This answer completely ignores the problem of passing real arrays into a function, which means the code might compile but will DTWT.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.