user081608
user081608

Reputation: 1113

Input array in constructor - Perl

I am currently creating a class in Perl that looks like this:

sub new{
   $class = shift;
   $self = {
     #Member Variables
     server => shift,
     type => shift,
     domains => shift
   };
   bless $self, $class;
   return $self;
}

I want the domains to be an array with multiple variables. How would I differentiate an array from a normal variable when using shift? I am trying to input the array like this:

 my $var = new class("server",1,(1,2,3));
 my $var = new class("server",1,[1,2,3]);

Neither of these work when trying to iterate through the array doing:

 for $i ($self->{domains}){
     print "$i\n";
 }

Upvotes: 1

Views: 631

Answers (2)

zdim
zdim

Reputation: 66881

Arguments are passed to a function as a list of scalars, and your first invocation is just

my $var = new class("server",1,1,2,3);

A hash value need be a scalar, so you need an anonymous array there

domains => [ LIST ];

So either

  • shift off all single options as you do and then copy the rest into the arrayref

    domains => [ @_ ];
    
  • or pass an arrayref, which is a scalar, like in your second invocation and assign it

    domains => shift;
    

In both cases the $self->{domains} is going to be an arrayref.

On the other hand, consider nicely assigning arguments first

sub new { 
    my ($class, $server, $type, @domains) = @_;
    # ...
    my $self = { 
        # ...
        domains => \@domains
    };
    return bless $self, $class;
}

for the first invocation, or

sub new {
    my ($class, $server, $type, $rdomains) = @_;
    my $self = {
        # ...
        domains => $rdomains
    };
    return bless $self, $class;
}

for the second one. Since bless returns its first argument we can directly return (for brevity).

Finally, you use the indirect object notation for calling the constructor. In short, don't -- use

my $object = ClassName->new( ARGS );

See the link above for an official statement, and this post


Please always run with warnings, as that saves a lot of headaches. I also strongly suggest to always use strict as it promotes all manner of good practices

# At the beginning of every program
use warnings 'all';
use strict;

Upvotes: 5

Sinan Ünür
Sinan Ünür

Reputation: 118128

If you want to specify domains as a list, you need to do this:

sub new {
   $class = shift;
   $self = {
     server => shift,
     type => shift,
     domains => [ @_ ],
   };
   bless $self, $class;
   return $self;
}

That's because hashes cannot have non-scalar keys or values.

Either way, you are going to have to dereference that array ref when iterating through domains:

for my $domain (@{ $self->{domains} }){
     print "$domain\n";
 }

Upvotes: 3

Related Questions