Search code examples
pragmaperl

What is perl feature, postderef?


I see use experimental 'postderef' and use feature 'postderef' being used in Moxie here on line 8. I'm just confused at what it does. The man pages for experimental are pretty vague too,

allow the use of postfix dereferencing expressions, including in interpolating strings

Can anyone show what you would have to do without the pragma, and what the pragma makes easier or possible?


Solution

  • What is it

    It's simple. It's syntactic sugar with ups and downs. The pragma is no longer needed as the feature is core in 5.24. But in order for the feature to be supported in between 5.20 and 5.24, it had to be enabled with: use experimental 'postderef'. In the provided example, in Moxie, it's used in one line which has $meta->mro->@*; without it you'd have to write @{$meta->mro}.

    Synopsis

    These are straight from D Foy's blog, along with Idiomatic Perl for comparison that I've written.

    D Foy example                    Idiomatic Perl
    $gimme_a_ref->()->@[0]->%*       %{ $gimme_a_ref->()[0] }
    $array_ref->@*                   @{ $array_ref }
    get_hashref()->@{ qw(cat dog) }  @{ get_hashref() }{ qw(cat dog) }
    

    These examples totally provided by D Foy,

    D Foy example                    Idiomatic Perl
    $array_ref->[0][0]->@*           @{ $array_ref->[0][0] }
    $sub->&*                         &some_sub
    

    Arguments-for

    • postderef allows chaining.
    • postderef_qq makes complex interpolation into scalar strings easier.

    Arguments-against

    not at all provided by D Foy

    • Loses sigil significance. Whereas before you knew what the "type" was by looking at the sigil on the left-most side. Now, you don't know until you read the whole chain. This seems to undermine any argument for the sigil, by forcing you to read the whole chain before you know what is expected. Perhaps the days of arguing that sigils are a good design decision are over? But, then again, perl6 is still all about them. Lack of consistency here.
    • Overloads -> to mean, as type. So now you have $type->[0][1]->@* to mean dereference as $type, and also coerce to type.
    • Slices do not have an similar syntax on primitives.

      my @foo = qw/foo bar baz quz quuz quuuz/;
      my $bar = \@foo;
      
      # Idiomatic perl array-slices with inclusive-range slicing
      say @$bar[2..4];   # From reference; returns bazquzquuz
      say @foo[2..4];    # From primitive; returns bazquzquuz
      
      # Whizbang thing which has exclusive-range slicing
      say $bar->@[2,4];  # From reference; returns bazquz
                         # Nothing.
      

    Sources