PerlOnTheWay has asked for the wisdom of the Perl Monks concerning the following question:

[test@test ~]$ perl -we ' package grand_father; use base qw/Class::Accessor::Fast/; sub new { my $class=shift; return $class->SUPER::new(@_); } package father; use base grand_father; sub new { my $self=shift->SUPER::new(@_); return $self; } package son; use base father; package main; use Data::Dumper; print Dumper(son->new);

output:

$VAR1 = bless( {}, 'son' );

It seems to me the line my $self=shift->SUPER::new(@_); should cause dead loop,but it actually works fine.

My reasoning:

As SUPER should look up new in its parent ,so dead loop will occur.

Anyone can explain how SUPER works ?

Replies are listed 'Best First'.
Re: Why doesn't SUPER cause dead loop here?
by ikegami (Patriarch) on Sep 02, 2011 at 02:46 UTC

    SUPER relates to the class in which the code using it is compiled. It doesn't involve the invocant.

    1. son->new looks in son and its ancestors for a new and calls father::new.
    2. shift->SUPER::new(@_) in father::new looks in father's ancestors for a new and calls grandfather::new.
    3. $class->SUPER::new(@_) in grandfather::new looks in grandfather's ancestors for a new and calls Class::Accessor::Fast::new.

    By the way, the behaviour of shift->SUPER::new(@_) is undefined. Don't modify and use a variable (@_) in the same statement.

      Let's focus on step 2

      shift->SUPER::new(@_)

      Here the result of shift should be son,right?

      then shift->SUPER::new should still call father::new,right?

        No, father is not in @father::ISA or a descendant of the classes therein.

        SUPER relates to the class in which the code using it is compiled. It doesn't involve the invocant.

        By the way, what's a dead loop? Is that the same thing as an infinite loop?

      By the way, the behaviour of shift->SUPER::new(@_) is undefined. Don't modify and use a variable (@_) in the same statement.

      I'm pretty sure, that unlike increment/decrement, or modifying an array in a foreach, this behaviour is defined

      shift(@_)->SUPER::new(@_)

        You say you think it's defined, but the only thing you gave to back that up is that other things aren't defined. Please show where it is defined if it is.

        The operand evaluation order is well known* for all operators, but it's only documented for some. It's not for the arrow operator (docs below). Off the top of my head, operand evaluation order is only defined for the following operators:

        • logical operators (for short-circuiting)
        • conditional operator (for short-circuiting)**
        • comma/list operator (so it can be used as a statement separator)
        • assignment (for my $x = $x; and local $x = $x;)***

        From perlop:

        "->" is an infix dereference operator, just as it is in C and C++. If the right side is either a [...], {...}, or a (...) subscript, then the left side must be either a hard or symbolic reference to an array, a hash, or a subroutine respectively. (Or technically speaking, a location capable of holding a hard reference, if it's an array or hash reference being used for assignment.) See perlreftut and perlref.

        Otherwise, the right side is a method name or a simple scalar variable containing either the method name or a subroutine reference, and the left side must be either an object (a blessed reference) or a class name (that is, a package name). See perlobj.

        As you can see, there's no mention of operand evaluation order.

        * — Meaning all existing versions of Perl use the same order.

        ** — Short-circuiting nature and thus operand evaluation order is not actually documented, but it is strongly expected.

        *** — Operand evaluation order is inferred from documented ability to do my $x = $x; and local $x = $x;.