Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Moo error message not understood

by davies (Prior)
on Jan 17, 2014 at 17:36 UTC ( [id://1070985]=perlquestion: print w/replies, xml ) Need Help??

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

use strict; use warnings; use diagnostics; use 5.014; my $newbook = Lib::Book->new( isbn => 'ISBN', ); say $newbook->isbn; package Lib::Book; use Moo; has isbn => ( is => 'rw', ); 1;

My code, in which I can see no material differences from the documentation (http://search.cpan.org/~haarg/Moo-1.004002/lib/Moo.pm), crashes as follows:

Z:\Data\Library\Dancer2>sopw.pl Can't locate object method "isbn" via package "Lib::Book" at Z:\Data\Library\Dancer2\sopw.pl line 9 (#1) (F) You called a method correctly, and it correctly indicated a pa +ckage functioning as a class, but that package doesn't define that parti +cular method, nor does any of its base classes. See perlobj. Uncaught exception from user code: Can't locate object method "isbn" via package "Lib::Book" at Z +:\Data\Library\Dancer2\sopw.pl line 9.

I'm slightly surprised by the error message's reference to an "object method" when I'm trying to address a property, but I suspect that this is merely a Perl idiosyncracy. The assignment in the "new" command works - printing the object using Data::Dumper reveals the isbn property set as I would expect. I tried inserting the "namespace::clean" line from the docs, but that changed nothing.

What should I look at next, please?

Regards,

John Davies

Replies are listed 'Best First'.
Re: Moo error message not understood
by tangent (Parson) on Jan 17, 2014 at 18:50 UTC
    hi davies. You would normally keep your modules in a separate file, in this case 'Book.pm' in a directory 'Lib', and I think the documentation assumes that is the case. If you do that (and use Lib::Book; in your script) the problem will go away.
Re: Moo error message not understood (BEGIN block missing)
by Anonymous Monk on Jan 17, 2014 at 17:57 UTC
    Its your basic order of compilation deal ...

    Lib::Book->new happens before  has isbn happens ...

    basically because that is what you typed, at the time new is called the class doesn't have isbn yet

    If you add  BEGIN { ... } around package Lib::Book, all that should happen before Lib::Book->new as you expect

    Don't know where all this is documented, maybe Simple Module Tutorial ... maybe its also discussed in tyes template at (tye)Re: Stupid question (and see one discussion of that template at Re^2: RFC: Creating unicursal stars

      Thanks. Your advice works perfectly, but I'm still confused. I don't see how, if the "new" happens before "has", the text gets into the object as shown by Data::Dumper. Maybe I shouldn't be worrying, but I'm scared there's a trap lying in wait for me.

      Regards,

      John Davies

      Update: Thanks again. I won't pretend to understand everything at first glance late on a Friday evening, but it's a relief to know that there is a sound explanation. I will work through it, but I won't guarantee how many attempts it will take to get it into my skull. I knew there were aspects of Perl I didn't have a clue about, and this is clearly one that I need to understand better.

        the text gets into the object as shown by Data::Dumper.

        Yes it does ... doesn't mean there is an accessor created (accessors are just "methods" aka "subroutines")

        without has bar

        use Data::Dump qw/ dd /; dd( my $f = Foo->new(qw/ bar 1 /) ); $f->bar; {package Foo; use Moo; } __END__ bless({ bar => 1 }, "Foo") Can't locate object method "bar" via package "Foo" at - line 3.

        you can cheat and use $f->{bar} ... this is cheating / breaking encapsulation / peeking inside object / not using official api / so if sometime in the future you internally rename bar attribute to barps, anyone using ->{bar} would have to update program, anyone using the documented api ->bar wouldn't (because you'd update that too) ... yeah seems convoluted example but thats how they work :)

        with has bar Without BEGIN block there is no bar accessor (accessor is subroutine ... all $obj->whatever is subroutines)

        use Data::Dump qw/ dd /; dd( my $f = Foo->new(qw/ bar 1 /) ); $f->bar; {package Foo; use Moo; has( qw/ bar is rw / ); } __END__ bless({ bar => 1 }, "Foo") Can't locate object method "bar" via package "Foo" at - line 3.

        with has bar and With BEGIN block no death :)

        use Data::Dump qw/ dd /; dd( my $f = Foo->new(qw/ bar 1 /) ); $f->bar; BEGIN{package Foo; use Moo; has( qw/ bar is rw / ); } __END__ bless({ bar => 1 }, "Foo")

        with has bar and Without begin block no death (moved to line 1)

        {package Foo; use Moo; has( qw/ bar is rw / ); } use Data::Dump qw/ dd /; dd( my $f = Foo->new(qw/ bar 1 /) ); $f->bar; __END__ bless({ bar => 1 }, "Foo")

        got that? See also perlobj, A Method is Simply a Subroutine, Attributes

Re: Moo error message not understood
by ikegami (Patriarch) on Jan 17, 2014 at 18:28 UTC
    use Some::Module;
    can be inlined as
    BEGIN { ... Contents of Some/Module.pm ... $INC{'Some/Module.pm'} = 1; } use Some::Module;

    (There are differences, such as lexical pragmas before the BEGIN block will also affect the BEGIN block, but it's a good starting point.)

    So what you want:

    use strict; use warnings; use diagnostics; use 5.014; BEGIN { package Lib::Book; use Moo; has isbn => ( is => 'rw', ); $INC{"Lib/Book.pm"} = 1; } use Lib::Book; my $newbook = Lib::Book->new( isbn => 'ISBN', ); say $newbook->isbn;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1070985]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (7)
As of 2024-03-28 20:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found