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

Hello Monks,

Apologies for the second sequential question, but I keep getting stack one question after the other.

I am trying to follow the tutorial Simple Module Tutorial in order to configure the code to my needs so I can use it on my module.

The error that I am getting is very common, but I can not find a solution or at least an indication on what I am doing wrong.

I have installed my molule Net::SNTP::Client by applying the following commands:

perl Makefile.PL make make test sudo make install

After I installed the Module::Starter from CPAN.

I assume that this is the reason that I am getting this error, so I tried to reinstall the module after the modification on the module file but the error remains the same.

Undefined subroutine &main::func1 called at client.pl line 9.

Can someone help understand what I am doing wrong?

Update 1: Adding client.pl script.

#!/usr/bin/perl use strict; use warnings; my @list = qw (J u s t ~ A n o t h e r ~ P e r l ~ H a c k e r !); use Net::SNTP::Client qw(&func1); print func1(@list),"\n";

Update 2: Adding Net::SNTP::Client.pm module.

#!/usr/bin/perl use strict; use warnings; use Exporter qw(import); package Net::SNTP::Client; our $VERSION = v5.18.2; # Or higher... our @ISA = qw(Exporter); our @EXPORT = (); our @EXPORT_OK = qw(func1 func2); our %EXPORT_TAGS = ( # Mappings for :shortcuts. DEFAULT => [ qw(&func1) ], BOTH => [ qw(&func1 &func2) ] ); sub func1 { return reverse @_ } sub func2 { return map{ uc }@_ } 1;

Final Update: Apologies for confusing so many people that tried to help me, by not been able to understand my problem.

I just figure it out. Not knowing something can lead to so many mistakes and disappointment!

Everyone is absolutely right, The way that I define my folders on my module was completely wrong!!!!!!!

I named my module literally Net::SNTP::Client.pm although that I read that when the module will be installed this will mean that will be in the directory Net/SNTP/Client I completely forgot about it and proceed with naming the module like this. So when I defined package Net::SNTP::Client.pm I ignored the fact that I need to create a directory Net/SNTP/ and include my module Client.pm

Of course when I was trying to load the module it was not able to see the directory since they do not match. So I simply used the use lib '/home/username/Desktop/Test/'; before loading my module and modified also the directories accordingly. I had to rename my module to Client.pm instead of Net::SNTP::Client.pm and voilą!

Expected output:

!rekcaH~lreP~rehtonA~tsuJ

Apologies for not been able to understand and explain my problem properly. I have confused to many people that tried to help me.

Thank you again in advance for your time and effort.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: Undefined subroutine &main::func1
by kcott (Archbishop) on Jun 28, 2015 at 02:13 UTC

    G'day thanos1983,

    "Can someone help understand what I am doing wrong?"

    Well, for that to happen, you need to show us what you are doing! And, frankly, after all the time you've been here, you really should know this. Please read "How do I post a question effectively?" (again, if necessary).

    My best guess, is that you've written code like:

    use Net::SNTP::Client; ... func1();

    When you should've written code like:

    use Net::SNTP::Client; ... Net::SNTP::Client::func1();

    or

    use Net::SNTP::Client qw{func1}; ... func1();

    -- Ken

      Hello kcott,

      Thank you for your time and effort reading and replying to my question.

      That is so true, I should have added the code it has a been long night here so my brain is extremely slow.

      Any way unfortunately I tried both of your solutions, very similar to my solution but again same error.

      This is the first time that I am using the Exporter module and not using Classes and Objects and I can not figure out why my code is not working.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        "Any way unfortunately I tried both of your solutions, very similar to my solution but again same error."

        The code you posted in your update has:

        use Net::SNTP::Client qw(&func1);

        But that update only shows client.pl. We have no idea what's in Net/SNTP/Client.pm!

        The suggestion I posted that's nearest to that is:

        use Net::SNTP::Client qw{func1};

        qw(&func1) (in client.pl) looks wrong to me, but I'm still just guessing!

        "This is the first time that I am using the Exporter module ..."

        Have you read, and fully understood, the documentation of Exporter.

        -- Ken

Re: Undefined subroutine &main::func1
by GrandFather (Saint) on Jun 28, 2015 at 02:11 UTC

    What does "client.pl line 9" look like? In fact, what do lines 1 - 9 look like?

    Most likely func1 comes from a module, but you haven't told Perl where to find it. You probably need something like:

    Net::SNTP::Client::func1();
    Perl is the programming world's equivalent of English

      Hello GrandFather,

      Thank you for your time and effort reading and replying to my question.

      I have updated my question with the part that was missing.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Undefined subroutine &main::func1
by Anonymous Monk on Jun 28, 2015 at 04:18 UTC

    Hi thanos1983
    Just before you go to bed, take a second look at this (Just for the fun of it! Nothing serious):

    pm code

    package Hommy; use warnings; use strict; use Exporter qw(import); our @EXPORT_OK = qw(teller); sub teller(\[$@%]); sub teller(\[$@%]) { my $in = shift; my $data = { SCALAR => sub { print join $/ => split // => ${ $_[0] } }, ARRAY => sub { print join $/ => @{ $_[0] } }, HASH => sub { for my $k ( sort keys $_[0] ) { print $k, join $/ => split // => $_[0]{$k}; } }, }; $data->{ ref $in }->($in); } 1;

    Then the pl script to use the pm

    use warnings; use strict; use lib '.'; # note here use Hommy qw(teller); teller @{[(split//=>"home sweet home!")]};
    You really, don't need to install your own module atleast you can manipulate the @INC at compile time. Check the note!

      Hello Anonymous,

      Thank you for your time and effort, reading and replying to my question.

      I assume the same, in theory I should install the module in order to be able to use it but before I reach this point to post this question Undefined subroutine &main I was not able to execute my code. See question How to create a reusable module with Exporter SOLVED, I still can not find a way to use new modules with the name eg. Net::SNTP::Something without installing them locally. I keep getting the same error if I do not install them:

      Can't locate Net/SNTP/Server.pm in @INC (you may need to install the N +et::SNTP::Server module) (@INC contains: . /etc/perl /usr/local/lib/p +erl/5.18.2 /usr/local/share/perl/5.18.2 /usr/lib/perl5 /usr/share/per +l5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl) +at server.pl line 8. BEGIN failed--compilation aborted at server.pl line 8.

      For example, I have another module that I want to use named Net::SNTP::Server.pm. For simplicity and demonstration purposes I am using the same code from Net::SNTP::Client.pm with only difference the package name. Sample of code provided bellow:

      #!/usr/bin/perl use strict; use warnings; use Exporter; package Net::SNTP::Server; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT = (); @EXPORT_OK = qw(func1 func2); %EXPORT_TAGS = ( DEFAULT => [qw(&func1)], Both => [qw(&func1 &func2)] ); sub func1 { return reverse @_ } sub func2 { return map{ uc }@_ } 1;

      I am calling it from the server.pl script. Sample of code provided under:

      #!/usr/bin/perl use strict; use warnings; my @list = qw (J u s t ~ A n o t h e r ~ P e r l ~ H a c k e r !); use lib '.'; # note here use Net::SNTP::Server qw(&func1); print func1(@list),"\n";

      The error that I am getting is the same:

      Can't locate Net/SNTP/Server.pm in @INC (you may need to install the N +et::SNTP::Server module) (@INC contains: . /etc/perl /usr/local/lib/p +erl/5.18.2 /usr/local/share/perl/5.18.2 /usr/lib/perl5 /usr/share/per +l5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl) +at server.pl line 8. BEGIN failed--compilation aborted at server.pl line 8.

      So at this point you will say that I am not using correctly the directories. I can not call a module Net::SNTP::Server.pm without installing it on the lib directory, can I?

      Thank you for your time and effort.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Undefined subroutine &main::func1
by soonix (Chancellor) on Jun 28, 2015 at 13:18 UTC
    What looks most suspicious to me (and perhaps to kcott), are the '&' sigils in your use and %EXPORT_TAGS. I'd try by removing them.
      What looks most suspicious to me (and perhaps to kcott), are the '&' sigils in your use and %EXPORT_TAGS.

      The ampersand is optional, but legal in the exporter variables (@EXPORT and @EXPORT_OK). Quoting Exporter:

      How to Export

      The arrays @EXPORT and @EXPORT_OK in a module hold lists of symbols that are going to be exported into the users name space by default, or which they can request to be exported, respectively. The symbols can represent functions, scalars, arrays, hashes, or typeglobs. The symbols must be given by full name with the exception that the ampersand in front of a function is optional, e.g.

      @EXPORT = qw(afunc $scalar @array); # afunc is a function @EXPORT_OK = qw(&bfunc %hash *typeglob); # explicit prefix on +&bfunc

      If you are only exporting function names it is recommended to omit the ampersand, as the implementation is faster this way.

      From that, I conclude that the ampersand is optional, but not recommended also in %EXPORT_TAGS and in parameters for import() (i.e. after use and require).

      The source code of Exporter actively removes leading ampersands in sub import:

      my $exports = \@{"$pkg\::EXPORT"}; # ... my $export_cache = ($Cache{$pkg} ||= {}); my $args = @_ or @_ = @$exports; if ($args and not %$export_cache) { s/^&//, $export_cache->{$_} = 1 foreach (@$exports, @{"$pkg\::EXPORT_OK"}); }

      The same logic also exists in Exporter::Heavy:

      sub _rebuild_cache { my ($pkg, $exports, $cache) = @_; s/^&// foreach @$exports; @{$cache}{@$exports} = (1) x @$exports; my $ok = \@{"${pkg}::EXPORT_OK"}; if (@$ok) { s/^&// foreach @$ok; @{$cache}{@$ok} = (1) x @$ok; } }

      Exporter::Heavy even adds ampersand prefixes sometimes:

      sub heavy_export { # ... my($pkg, $callpkg, @imports) = @_; my($type, $sym, $cache_is_current, $oops); my($exports, $export_cache) = (\@{"${pkg}::EXPORT"}, $Exporter::Cache{$pkg} ||= {}); # ... my($fail, $fail_cache) = (\@{"${pkg}::EXPORT_FAIL"}, $Exporter::FailCache{$pkg} ||= {}); if (@$fail) { if (!%$fail_cache) { # Build cache of symbols. Optimise the lookup by adding # barewords twice... both with and without a leading &. # (Technique could be applied to $export_cache at cost of memo +ry) my @expanded = map { /^\w/ ? ($_, '&'.$_) : $_ } @$fail; warn "${pkg}::EXPORT_FAIL cached: @expanded" if $Exporter::Ver +bose; @{$fail_cache}{@expanded} = (1) x @expanded; } my @failed; # ... } # ... }

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        Ah. I think I mixed that up with the inadvertently-prototype-creating use of '()'. Thank you for the elaborated enlightenment.

        I must admit that I hadn't run the "problematic" code. I just did, and made the following observations.

        1. first, I tried it in the same directory, changing the file name to TestClient.pm and modified package name use statement accordingly.
          The thing worked.
        2. now I created Net and Net//SNTP folders, moved and renamed the .pm file.
        3. After receiving a "can't locate in @INC" message I realized I hadn't correctly moved the module :-)
        4. Now i got the message in the OP! - (although line 8, not 9)
        5. Then it dawned on me: I hadn't changed back the package statement! After correcting this, it worked again.
        So, thanos1983, I bet the module in your post are different from ehat you have on your disc. Check the spelling in your package statement!

        Hello afoken,

        Thank you for your time and effort reading and replying to my query.

        Well after a lot of experimentation I have concluded that the problem lies with the directories. I am using Net::SNTP::Client.pm which I have install it locally. I assume since the moment that I install it locally since then any modification I am applying on the module is ignored because I can see the installed directory Net-SNTP-Client.

        So I assume that I first need to uninstall the module and then find a way to experiment with the module before installing it.

        I have tried almost 100 different combinations with the use lib '/home/username/ModuleFolder/'; but I keep getting the same error:

        Can't locate Net/SNTP/Client.pm in @INC (you may need to install the N +et::SNTP::Client module) (@INC contains: /home/tinyos/Desktop/Test /h +ome/tinyos/Desktop/Test/ /etc/perl /usr/local/lib/perl/5.18.2 /usr/lo +cal/share/perl/5.18.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5 +.18 /usr/share/perl/5.18 /usr/local/lib/site_perl .) at client.pl lin +e 8. BEGIN failed--compilation aborted at client.pl line 8.

        I have unistalled my module since I think this is the root of all problems before I move to the next step I need to find a way to make it work.

        Sample of Module Net::SNTP::Client.pm:

        #!/usr/bin/perl use strict; use warnings; use Exporter; package Net::SNTP::Client; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT = (); @EXPORT_OK = qw(func1 func2); %EXPORT_TAGS = ( DEFAULT => [qw(&func1)], Both => [qw(&func1 &func2)] ); sub func1 { return reverse @_ } sub func2 { return map{ uc }@_ } 1;

        Sample of code for script client.pl:

        #!/usr/bin/perl use strict; use warnings; my @list = qw (J u s t ~ A n o t h e r ~ P e r l ~ H a c k e r !); use lib '/home/username/Desktop/Test'; use Net::SNTP::Client qw(func1); print func1(@list),"\n";
        Seeking for Perl wisdom...on the process of learning...not there...yet!

      Hello soonix,

      Thank you for your time and effort reading and reviewing my code.

      Well if I am not mistaken (I am not really sure since I have no experience with reusable modules) that the '&' is not affecting the code on %EXPORT_TAGS because I am not using them, not yet at least.

      Based on the example Simple Module Tutorial the author is using these sigils and they work fine, I just tested it. I assume the error comes from the Directories that I using Net::SNTP:Client.pm can not be used without been installed.

      Or maybe I am doing many wrong assumptions.

      Any way I am still working on it to learn more about it, thank you for your time and effort again.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Undefined subroutine &main::func1
by stevieb (Canon) on Jun 28, 2015 at 02:27 UTC

    If you call func1 () from at the botbottom of your actual module, does it work?

      Hello stevieb,

      I did not think about that. I did test it and it does work inside the module, but again not from the script.

      Thank you for your time and effort.

      Seeking for Perl wisdom...on the process of learning...not there...yet!