Hannibal
Hannibal

Reputation: 445

How to determine, in a Moose constructor, what context it was called in?

Let's say we have a Moose class like so:

package My::Test ;
use Moose ;
$\="\n";

sub BUILDARGS {
    my ($pkg,%args) = @_ ;
    print defined wantarray ? 'BUILDARGS: SCALAR':'BUILDARGS: VOID' ;
    return \%args ;
}

sub BUILD {
    print defined wantarray ? 'BUILD: SCALAR':'BUILD: VOID' ;
    my ( $self, $args ) = @_ ;
    print '---' ;
}
1;

Instantiating the class in both SCALAR and VOID context I get always the same output:

#!/usr/bin/perl
use Moose ;
use My::Test ;
# Scalar ctx
my $instance = My::Test->new ;
# Void ctx
My::Test->new ;

Output:

BUILDARGS: SCALAR
BUILD: VOID
---
BUILDARGS: SCALAR
BUILD: VOID

I was able to get the context wrapping the Moose class instance creation in a trivial package and passing the context as constructor attribute as follows:

package My::Wrapper ;
use My::Test ;
sub new {
    my ( $class , %args ) = @_ ;
    return My::Test->new(%args , ctx => defined wantarray ? 'scalar':'void') ;
} 
1 ;    

but I would like to know if there is a cleaner way for doing that.

Upvotes: 2

Views: 95

Answers (1)

choroba
choroba

Reputation: 241908

Moose creates the constructor for you (see here). The context isn't propagated to either BUILDARGS or BUILD.

You can wrap new in the Moose way, though:

around new => sub {
    my ($orig, $self) = splice @_, 0, 2;
    warn defined wantarray ? 'other' : 'void';
    $self->$orig(@_)
};

Upvotes: 6

Related Questions