How do I handle optional parameters in Moose?

北战南征 提交于 2019-12-08 17:50:20

问题


I'm currently starting with Perl OOP using the "Moose" package.

The compiler complains that it "Can't modify non-lvalue subroutine call at Parser.pm line 16."

I don't quite understand why I can't just assign a new object. I guess there is a better or more valid way to do optional parameters with Moose?

    #!/usr/bin/perl -w

package Parser;

use Moose;

require URLSpan;

require WWW::Mechanize;

has 'urlspan' => (is => 'rw', isa => 'URLSpan', required => 1);
has 'mech' => (is => 'rw', isa => 'WWW::Mechanize');

sub BUILD {
    my $self = shift;
    if(!$self->mech) {
        warn("no Mech set for " . $self->urlspan->name);
        $self->mech = WWW::Mechanize->new(agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.4',
                                         stack_depth => 1
                                         ); #line 16
        }

}

回答1:


$self->mech is a method call; you can't really treat it like a field in a C struct. If you want to set it, you need to pass the new object to it.

        $self->mech( 
            WWW::Mechanize->new(
                agent => 'xyz',
                stack_depth => 1
            )
        );



回答2:


Probably the preferred Moose way of doing this is to set lazy_build on the attribute:

has 'mech' => (is => 'rw', isa => 'WWW::Mechanize', lazy_build => 1);
sub _build_mech {
     warn("no Mech set for " . $self->urlspan->name);
     WWW::Mechanize->new(
           agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.0.6)'.
                    ' Gecko/2009011913 Firefox/3.0.4',
           stack_depth => 1
     );
}

This will allow the attribute 'mech' to get populated the first time it is called, unless otherwise set by the constructor or by the accessor (since it's still 'rw').




回答3:


While Perl has provided the ability to use attributes the way you are trying to for a good many years (via what are called lvalue subs), it's not something that was in the first OO Perl releases, and people pretty much learned to do without it. Especially since implementing validation is a little tricky (and inefficient).

You could use MooseX::Meta::Attribute::Lvalue, but (according to the doc) at the cost of not having type checking on some attributes.

I'd recommend just sticking to the $self->attribute( "value" ) style.



来源:https://stackoverflow.com/questions/582427/how-do-i-handle-optional-parameters-in-moose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!