Thaddius
Thaddius

Reputation: 335

Perl, shift if(@_)

Can someone tell me what

shift if(@_)

means in perl?

and so what would

sub id {
   my $self = shift;
   $self->{ID} = shift if @_;

   return $self->{ID};
}

mean? Thanks.

Upvotes: 2

Views: 1486

Answers (5)

Miller
Miller

Reputation: 35198

That is a handrolled accessor/mutator for an object

print $obj->id;       # Accessor form
$obj->id(NEW_VAL);    # Mutator form

It is functionally equivalent to:

sub id {
    my $self = shift;
    if (@_) { # If called with additional parameters, set the value:
         $self->{ID} = shift(@_);
    }
    return $self->{ID};
}

Upvotes: 5

Barmar
Barmar

Reputation: 781068

There is no shift if @_ in your example -- if applies to the entire statement, not just the shift expression (because if has very low precedence in the expression hierarchy).

$self->{ID} = shift if @_;

is short for:

if (@_) {
    $self->{ID} = shift;
}

shift with no argument pulls the first element off the @_ list, so this sets $self->{ID} to the first argument of the subroutine if there are any arguments.

The general rule regarding postfix use of if is that:

<expression1> if <expression2>;

is short for:

if (<expression2>) {
    <expression1>;
}

Upvotes: 0

Joe McMahon
Joe McMahon

Reputation: 3382

shift if(@_) says "if @_ has any elements (i.e., evaluating @_ in scalar context is greater than zero), shift off the first element of the default argument (inside a subroutine, this is @_)".

The sub is a standard pre-Moose setter/getter method. Commented to explain:

sub id {
    my $self = shift;   # @_ is the implied argument of shift.
                        # Since method calls prepend the object reference to @_,
                        # this grabs the object itself, assumed by the later code
                        # to be a hash reference.

    $self->{ID} = shift if @_;
                        # If there's still anything left in @_ (`if @_`), get
                        # the first item and stash it under the ID key in 
                        # the hash referenced by $self (note that if there is more
                        # than one item, we'll only stash the first one).

    return $self->{ID}; # Return whatever the value of the item stored under ID in the
                        # hash referenced by $self is. This will be the value just 
                        # assigned if the method was called with a scalar argument, 
                        # or whatever value was there before if no argument was passed.
                        # This will be undef if nothing was ever stored under the ID key.
}

Invocation would be

$obj->id();

to fetch, and

$obj->id($value);

to set.

A standard pre-Moose constructor would create an anonymous hash reference, bless it to turn it into an object (connecting a package implementing the class's behavior to that reference), and return it:

sub new {
    my($class) = @_;     # List assignment to a list; puts first item in one into the first
                         # item in another; a call to a class method prepends the package
                         # (class) name to @_, so this gets us the name of the class this
                         # object is to belong to.
    my $self = {};       # Gets a new anonymous hash reference into $self.
    bless $self, $class; # Connects the hash reference to the package, so that method calls
                         # made on this object are directed to this class (and its @ISA
                         # ancestors) to find the sub to be called to implement the method.
    return $self;        # Hands the object back to the caller.
}

Upvotes: 1

mpapec
mpapec

Reputation: 50647

In a sub, shift without argument uses @_ array.

So

$self->{ID} = shift if @_;

is equal to

$self->{ID} = shift(@_) if @_;

(remove leftmost element from @_ array and assign it to $self->{ID})

Upvotes: 4

darch
darch

Reputation: 4311

shift takes the first element off an array and returns it. If no array is given, it operates on @_, the array containing function arguments. The if @_ statement modifier causes the preceding statement to be executed only if @_ has at least one element.

In your example, $self->{ID} = shift @_ if @_; means "If there is a function argument, assign it to $self->{ID}.

Upvotes: 1

Related Questions