Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the '@(' doing in this Perl code?

In this code snippet:

    use strict;
    use warnings;
    use Data::Dumper;
    my $r = [qw(testing this thing)];

    print Dumper($r);
    foreach my $row (@({$r})
    {
        print "$row\n";
        $row .= 'mod';
    }
    print Dumper($r);
    print Dumper(@({$r});

I figured out that the '(' after the '@' in the foreach is causing this not to loop correctly. I have no idea why this code even works as there is no ending parenthesis. What is this doing? It looks to be creating a new variable on the fly, but shouldn't 'use strict' have fired or something?

Please help explain what that '@(' is doing and why it still runs without an ending parenthesis.

like image 786
Anthony Veckey Avatar asked Nov 22 '11 01:11

Anthony Veckey


People also ask

What does ~~ mean in Perl?

Just as with the =~ regex match operator, the left side is the "subject" of the match, and the right side is the "pattern" to match against -- whether that be a plain scalar, a regex, an array or hash reference, a code reference, or whatever.

What is @_ and $_ in Perl?

$_ - The default input and pattern-searching space. @_ - Within a subroutine the array @_ contains the parameters passed to that subroutine. $" - When an array or an array slice is interpolated into a double-quoted string or a similar context such as /.../ , its elements are separated by this value.

What is $_ in Perl script?

The most commonly used special variable is $_, which contains the default input and pattern-searching string. For example, in the following lines − #!/usr/bin/perl foreach ('hickory','dickory','doc') { print $_; print "\n"; }

What is $# in Perl?

$#array is the subscript of the last element of the array (which is one less than the length of the array, since arrays start from zero). Assigning to $#array changes the length of the array @array, hence you can destroy (or clear) all values of the array between the last element and the newly assigned position.


1 Answers

That is a hash slice of the %( variable, which being part of the *( glob, is exempt from strict vars. This is true for variables that Perl has predefined, in this case $( and also for all of the other glob slots for the names of punctuation variables. All punctuation variables are global across all packages, and their fully qualified names are the short forms: $), @), %), &)... Since strict 'vars' does not apply to fully qualified names, none of these names are errors.

Expanding a bit:

@({$r};
@{(}{$r};
@{'main::('}{$r};  # needs strict refs to be off

Those lines are all equivalent.

With use warnings; perl will let you know that it would be better to write a slice of a single value with a $ sigil:

$({$r};
${(}{$r};
${'main::('}{$r};  # needs strict refs to be off

Which in trying to resolve a typo would have pointed you in the right spot. Which is why you should always use both warnings and strictures.

For more detail, the perlvar manpage shows all of the punctuation variables with at least one sigil or another. And if you wanted a reference about the scoping of punctuation variables, the package docs have that.


All the punctuation variables are also immune to used only once warnings, and that might be a bug...

like image 154
Eric Strom Avatar answered Nov 15 '22 20:11

Eric Strom