Home > Back-end >  What does this perl snippet with unary plus do? join( '/', splice @t, 0, @d )
What does this perl snippet with unary plus do? join( '/', splice @t, 0, @d )

Time:04-07

What does this perl snippet with unary plus do?

join( '/', splice @t, 0,  @d )

This is from File::Path.pm line 267, and I'm trying to understand it. According to the documentation, unary plus does nothing. Also the 3rd argument to splice is an integer, not an array. Does this actually do a scalar(@d)? Thanks for your help. I'm trying to translate this code with my Pythonizer to python.

I tried using -MO=Deparse and all it does is eat the and move the parens around:

join '/', splice(@t, 0, @d);

CodePudding user response:

The is completely useless here.


The author probably thought @d was a short version of scalar(@d), but they were mistaken if so.

Unary- has no effect on context.[1] Unary- has no effect at all. Quote perlop,

Unary " " has no effect whatsoever, even on strings. It is useful syntactically for separating a function name from a parenthesized expression that would otherwise be interpreted as the complete list of function arguments. (See examples above under "Terms and List Operators (Leftward)".)

It's can be used to disambiguate between ambiguous syntax,[2] but it doesn't even do that in the above snippet. It is completely superfluous.[3]

That said, @d is evaluated in scalar context here, but that's because the splice operator imposes scalar context on its third operand.[4] It has nothing to do with the unary- .

As such, another possibility is that the author wanted to signal that there's something unusual about @d here. One would probably expect it to be evaluated in list context, and the is designed to make the reader stop to think.

However, that's not something I would recommend doing. Instead of using the misleading @d, I would use 0 @d to achieve this goal. 0 @d actually imposes scalar context, so it signals that @d is being evaluated in scalar context, and it does so without being misleading.


  1. The following demonstrates that unary- doesn't affect context:

    $ perl -Mv5.10 -e'
       my @a = qw( a b c );
       my $x_without =  @a;  say $x_without;
       my $x_with    =  @a;  say $x_with;
       my @y_without =  @a;  say @y_without;
       my @y_with    =  @a;  say @y_with;
    '
    3
    3
    abc
    abc
    
  2. See using unary- to disambiguate.

  3. The following demonstrates the exact same code is produced with and without the unary- .

    $ diff -u \
       <( perl -MO=Concise,-exec -e'join( '/', splice @t, 0,  @d )' 2>&1 ) \
       <( perl -MO=Concise,-exec -e'join( '/', splice @t, 0,  @d )' 2>&1 ) \
    && echo same
    same
    
  4. The following demonstrates that the third operand is evaluated in scalar context:

    $ perl -Mv5.10 -e'say prototype( "CORE::splice" ) // "none/special"'
    \@;$$@
    

CodePudding user response:

The unary is sometimes useful to tell the parser how to interpret the following expression. See perlop:

Unary has no effect whatsoever, even on strings. It is useful syntactically for separating a function name from a parenthesized expression that would otherwise be interpreted as the complete list of function arguments.

In this particular case, though, it does nothing, as the @d is parsed as the third argument to splice and it's interpreted in scalar context, regardless of the presence of the .

CodePudding user response:

The prototype of splice is \@;$$@, so the optional third argument is going to be interpreted in scalar context, with or without a unary plus.

The interesting challenge for porting to Python is handling the side-effects of splice.

The return value of splice (which is what will get passed to the join function) are the elements of @t that are removed by the operation -- namely the first scalar @d elements of @t. But the @t array will be modified by the call, and after this statement it will be missing those first few elements.

  • Related