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

Monks, what is the + in +shift doing here?
# http://prometheus.frii.com/%7Egnat/yapc/2000-stages/slide47.html # (Nathan Torkington on Opaque Objects) sub new { my $value = 0; bless sub { local $_ = shift; /get/ and return $value or /set/ and $value = shift or die "Unknown method: $_"; }, shift; } sub get { +shift->("get", @_) } sub set { +shift->("set", @_) }
Where is this documented?

This idiom is also mentioned in Re: Perl parser tortured (was: Perl Idioms Explained) but I still don't understand it.

Replies are listed 'Best First'.
Re: What is the + in +shift doing here?
by gellyfish (Monsignor) on Feb 23, 2005 at 17:18 UTC

    It is just a way of disambiguating the shift (or any other function name for that matter) in a location where it might be mistaken for another bareword lexical item. You will often find this (most commonly IMO) in print statements such as:

    print +join '', @array;
    where the join would be misparsed as being a filehandle rather than a function.

    The reason that the unary + is used is that it is syntactically valid (for reasons of symmetry I guess) but is a no-op.

    /J\

Re: What is the + in +shift doing here?
by Anonymous Monk on Feb 23, 2005 at 17:18 UTC
    Unary plus is a NOP. However, it prevents from what follows being interpreted as a bareword, and hence, from being autoquoted. It shouldn't be necessary in this case, but it could be older versions of perl were confused. Or it was part of some older (now gone) code that required the +. Or the author has a habit.

    It's not necessary in this case. But in the following case, it would:

    sub get {$some_hash{+shift}->("get",@_)}
    Without the +, it's equivalent to:
    sub get {$some_hash{"shift"}->("get",@_)}
    but with the +, it's equivalent to:
    sub get {$some_hash{shift(@_)}->("get",@_)}
    But that's more typing.
Re: What is the + in +shift doing here?
by davido (Cardinal) on Feb 23, 2005 at 17:22 UTC

    It's ensuring that shift is being evaluated as a function call and not as a literal string. You don't want 'shift' to be seen as a class name, you want it to be evaluated as a function call, and its return value to be used as the class name or object reference.

    Examples:

    my $object = Classname->new(); # Classname is seen as a class name # and new() is a method of Classname. my $gotten = +subname->new(); # Here subname had better return # either a valid class name or an # object capable of having new() # called as an object method.

    Dave

      It's ensuring that shift is being evaluated as a function call and not as a literal string.
      But the only case where that can occur is when the function name might be subject to autoquoting. For instance, on the left hand side of a fat arrow. But all we have here is a thin arrow.
      You don't want 'shift' to be seen as a class name, you want it to be evaluated as a function call, and its return value to be used as the class name or object reference.
      Look again at the original code. The return value of the shift is not treated as a class or an object. Look what's following the arrow: not a method name! The return value of the shift is considered to be a subroutine reference (could be a closure).
      Examples:
      Examples that have nothing to do with the original code. And the + doesn't do what you imply either. Classname->new() is only going to do a call to Classname::new() if there isn't a Classname() subroutine in the currect package. And a + isn't going to change that:
      #!/usr/bin/perl use strict; use warnings; package Class; sub foo {"Hello, world"} package Evil; sub foo {"All your base are belong to us"} package main; sub Class {"Evil"} sub bar1 {Class->foo} sub bar2 {+Class->foo} sub bar3 {"Class"->foo} print bar1, "\n"; print bar2, "\n"; print bar3, "\n"; __END__ All your base are belong to us All your base are belong to us Hello, world
Re: What is the + in +shift doing here?
by Roy Johnson (Monsignor) on Feb 23, 2005 at 17:48 UTC
    Saving a keystroke vis a vis the more clear shift(). Some people are alarmingly parentheses-averse.

    Caution: Contents may have been coded under pressure.
      And shift() saves two keystrokes vis a vis to the more clear shift(@_). Some people are alarmingly implicite variable-averse.

      Luckily, many people that are parenthesis-averse, or implicite variable-averse program in a language more suitable for them.

        There's nothing "more clear" about shift(@_). We're talking about disambiguating something; to make it clear that it's a function call, parentheses make the most sense. There is nothing ambiguous about leaving the argument implicit, and there's certainly nothing alarming about using implicit variables, just as there's nothing alarming about omitting the parentheses. But using a + instead of the parentheses is economy at the expense of clarity, which is alarming.

        The coward posts anonymously, then logs in to downvote the response.