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

I'm using Moo.pm ($VERSION = '2.000001';) and using 'extends' to build up inheritance.

This works fine, yet if I make an edit that will not compile (not my intention, but it sometimes happens, in this case the semi colon after handleDUM), the compile error is messed up:

mheSim.pl -type CRANESWL

Can't locate object method "checkArgs" via package "CRANESWL" at mheSim.pl line 37.

Please see my code below. Note that I've cut it down to be as short as possible to be relevant to this problem

My guess is that I'm not using Moo correctly and I should be using either Tiny::Roles or Moo::Roles, but without the compilation error it all works fine.

package MHE; use Data::Dumper; ################################################## use Moo; use Sub::Quote; my $args = (); has heartbeat => ( is => 'ro', default => sub { $args->{heartbeat} || 10; } ); ################################################## # End of oo setup ################################################## sub checkArgs { my ($self, $args) = @_; pod2usage( -msg => "No IP address specified\n", -verbose => 1 ) unless $args->{ip}; } 1;
and
package CRANESWL; use Moo; extends 'MHE'; has type => ( is => 'ro', default => 'CRANESWL', ); ################################################## # Handle incoming messages ################################################## # hash to define what sub to call dependant upon what msg type my $msgTypes = { DUM => \&handleDUM; }; 1;

and the main script:

#!/usr/bin/perl -w use FindBin qw($Bin); use Getopt::Long; use strict; # Set Library path for MHE modules use lib "$Bin/../lib"; use MHE; my $opts = { }; GetOptions($opts, 'type:s', ); # Use the object dependant upon the requested Type eval "use MHE::$opts->{type} qw(sendHeartbeat)"; my $mhe = $opts->{type}->new; $mhe->checkArgs($opts);

Replies are listed 'Best First'.
Re: Using Moo.pm and compilation errors
by Corion (Patriarch) on Apr 30, 2015 at 10:27 UTC

    eval swallows all errors. This is not what you want if you suspect compile-time errors in your code. Instead, use require, especially when using OO-style modules:

    ... my $class="MHE::" . $opts->{type}; my $filename= $class) =~ s!::!/!g; require "$filename.pm"; ...

    Alternatively, you can check $@ after the eval for errors:

    eval "use MHE::$opts->{type} qw(sendHeartbeat); 1" or die "Couldn't load 'MHE::$opts->{type}': $@";

      require "$filename.pm";

      :) Module::Load is core long time :)

      $ perl -e"use Module::Load; load q/longtime/; " Can't locate longtime.pm in @INC (@INC contains:...

        Great! I didn't know that module. I reused the code that parent.pm uses to load classes. The sad thing is that parent still supports 5.8.x and Module::Load came into (core) existence in 5.9.x and I'm somewhat reluctant to ditch one regex for another use line in parent.pm. But for all my other module-loading needs, Module::Load is a welcome find!

      Thanks! That works brilliantly. I was assuming the error was in Moo, rather than the eval.

        Just for clarity, the eval or did not work, so I used the following code:

        eval "use MHE::$opts->{type} qw(sendHeartbeat)"; die "Couldn't load 'MHE::$opts->{type}': $@" if $@;