novacik
novacik

Reputation: 1507

Parenthesis in a perl function call

AFAIK, parenthesis in perl are for:

so,

my $r = ($x+$y) * $z;
my(@l) = (1,2,3);

What is a meaning of a parenthesis in a function call? I didn't find any, the sub will get a simple list of its arguments.

#!/usr/bin/env perl

use Modern::Perl;
use Data::Dumper;

sub xxx { say Dumper \@_ }

xxx( 1,  2, 3  );
xxx( 1, (2, 3) );
xxx  1, (2, 3)  ;
xxx  1,  2, 3;

right?

Asking because the perl -MO=Deparse didn't remove the parenthesis from the function calls.

so for the next short script

use Moose;
has 'arg' => (is=>'rw', isa=>'Str');

returns

has('arg', ('is', 'rw', 'isa', 'Str'));

and not the simple

has('arg', 'is', 'rw', 'isa', 'Str');

Is here any difference?

Upvotes: 3

Views: 337

Answers (2)

amon
amon

Reputation: 57600

When the parens are not removed by deparsing, this is because they can be used to determine precedence. The snippets has('arg', 'is', 'rw', 'isa', 'Str') and has('arg', ('is', 'rw', 'isa', 'Str')) produce different Opcodes (although in this case the difference could be removed safely).

Parens do not create lists. “Lists” in Perl are not distinct data structures. They are just a more accessible description of a stack segment. If anything would create a list, then it would be the comma operator , in list context. (But it doesn't as there are no lists).

If the subroutine you are calling is known at parse time, then the parens from a function invocation are optional, i.e. the syntax is either any_function(@args) or known_function @args. Known functions can also use prototypes to change how the arguments are parsed (regardless of whether parens where used). For known functions it is not relevant whether the deparsed call uses parens, or not: both produce the same Opcodes.

Upvotes: 2

tobyink
tobyink

Reputation: 13664

In your examples, an exception to "they're all the same" would be something like this:

xxx (1,2), 3;

The difference between the following:

has('arg', ('is', 'rw', 'isa', 'Str'));
has('arg', 'is', 'rw', 'isa', 'Str');

is that the former builds one list, then builds a second list, pushing the first list onto it. The latter builds everything as a single list. You can see the difference using B::Concise; they compile to slightly different op trees. The former example will run ever so slightly slower, but there's little difference in it.

use strict;
use warnings;
use Benchmark qw(cmpthese);

cmpthese(-5, {
  once   => q[  my @x = (foo => (bar => 1, baz => 2))  ],
  twice  => q[  my @x = (foo =>  bar => 1, baz => 2 )  ],
});

__END__
       Rate twice  once
twice 216835/s    --   -1%
once  218228/s    1%    --

Upvotes: 3

Related Questions