Perl v.42 private methods

Exploring new Perl feature


New perl v.42 (in which I skipped the "5" because "v" is already "5" in Roman) was released last week. Its perldelta states:

Lexical method invocation operator ->&

Along with the ability to declare methods lexically, this release also permits invoking a lexical subroutine as if it were a method, bypassing the usual name-based method resolution.

Combined with lexical method declaration, these two new abilities create the effect of having private methods.

I decided to explore how this new operator would work in a real life scenario.

It's not magic, it's just syntax sugar

Perl "having private methods" is a bit of an overstatement. These private methods are really just regular lexically-scoped named functions which can now be called in a more OO-like way. They still obey lexical scoping rules, for example:

use v5.42;

package Test {
        my sub private ($self)
        {
                say 'hello world';
        }

        sub public ($self)
        {
                $self->&private;
        }
}

my $obj = bless {}, 'Test';
$obj->public

This works and prints hello world. However, public method must be placed below private to avoid compilation error. private only comes to life at the line of its declaration due to lexical scoping. This also means it's impossible to have two lexical methods calling each other (unless there is a way to pre-declare a lexically scoped method, which I am not aware of).

Calling $self->&private is the same as calling private($self), but prettier. It kind of reminds me of an indirect method call, but less magical.

Recursion in lexical subs

Can private call itself though? Yes, but not by calling $self->&private. __SUB__ keyword must be used, and I could not find a more concise way of doing it than this:

my sub private ($self)
{
        my $me = __SUB__;
        $self->$me;
}

Or with reversed order (which kind of defeats the purpose of ->&):

my sub private ($self)
{
        __SUB__->($self);
}

Knowing if a lexical sub exists

Would you like to know whether your object contains a lexical private method by name? It may be a bit hard since $self->can('private') does not work. For normal functions, you could check exists &function, but it does not recognize lexical functions. You either need to resort to some glob trickery or create a hashmap with lexical subs references as values. The point is: these functions do not seem to fall under the same category as normal functions, so your regular approaches may not yield positive results.

Better performance

It should not be surprising that calling any sub with ->& is faster. This is because we are skipping dynamic method resolution. Here are simple benchmark results on my machine. Note: both subs were empty - the difference would be barely noticeable if they did any non-trivial work.

              Rate  public private
public   9267717/s      --    -17%
private 11223290/s     21%      --

Beware of bugs!

During my testing I encountered and reported a nasty bug that comes from a combination of new Perl features. The bug causes segmentation fault of the program during the Perl compilation stage. It turns out this is the side effect of performance improvements of the indexed builtin. Until it is resolved, avoid using the combination of features mentioned in this GitHub issue.

Conclussion

So, do we now have private methods and can stop using underscored _methods in our code for that purpose? Definetly not, but they can still be useful. There are times where you really want to move part of the code to a simple helper in a separate method. This code will likely be pointless to call from any other context - this is a great use case for lexical subs, and the new operator makes them less awkward to call in OO code. Writing every private method with lexical subs could quickly backfire if they were to call each other or be called dynamically by name.


Comments? Suggestions? Send to bbrtj.pro@gmail.com
Published on 2025-07-09