3

I am new to Perl and I face following issue, having no clue why following is not working.

My Perl module contains:

package PACK2;
use Exporter;
@ISA = ('Exporter');
@EXPORT_OK=('whom');

sub why(){
    print "why\n";
}

sub whom(){
      print "whom\n";
}
1;

My Perl file contains:

#!/usr/bin/perl -w

use pack;
use pack2 ('whom');

PACK::who();
&whom();

I run this program and can't find whom:

perl use_pack_pm.pl

who
Undefined subroutine &main::whom called at use_pack_pm.pl line 7.
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Joe
  • 403
  • 1
  • 6
  • 12
  • 3
    I don't know for sure, so I'm not posting this as an answer, but I believe case sensitivity might be in play here. (You call your package "PACK2" but use "pack2" and the file is called "pack2.pm". All those need to be the same, I think!) – Platinum Azure Sep 15 '10 at 15:29
  • 3
    USUW -> `use strict; use warnings;`!! If you have a question of *why* isn't something happening--please use the facilities the language makes available. If you need to `print "$@\n$!\n";` If you don't understand a warning sufficiently `use diagnostics;`. – Axeman Sep 15 '10 at 15:39

3 Answers3

8

Perl is a case-sensitive language. I don't think modules "pack2" and "PACK2" are the same. (But I haven't actually tested this.)

reinierpost
  • 8,425
  • 1
  • 38
  • 70
  • Yes your are right after changing the file name to PACK2.pm it works fine. In that case perl behaves two different way in two different case. In my above example use pack; the first module is working fine.here is what contain in the first module..........................> cat pack.pm package PACK; sub why(){ print "why\n"; } sub who(){ print "who\n"; } 1 – Joe Sep 15 '10 at 15:34
  • You're right. They are wholly different packages. Thus, Perl *loads* `pack2.pm`, and does not `use` PACK2 package. Probably, using warnings would have told you this. – Axeman Sep 15 '10 at 15:36
  • i used warning which didn't give me any warning message.#!/usr/bin/perl -w – Joe Sep 15 '10 at 15:38
  • @user427394, well that's a part I didn't research. It's a good thing to remember that Perl is a UNIX-world language: case sensitive. And a UNIX hack sees this almost immediately. It runs on a variety of platforms, but it is most at home on *nix. – Axeman Sep 15 '10 at 15:43
  • use strict; and use warnings; as well don't catch that error. :( – Joe Sep 15 '10 at 15:46
  • 3
    Sometimes case-preserving but case-insensitive filesystems let people get away with these case issues. – brian d foy Sep 15 '10 at 15:47
  • 1
    Also be aware that not all shells honour options on the shebang line. That's why it's always better to write use warnings instead of appending -w there. – reinierpost Sep 15 '10 at 16:12
  • 1
    @reinierpost, perl will always try to read the switches on the #! line of the executed file even if the shell doesn't. `use warnings;` is still preferable for other reasons, like not enabling warnings in code expecting to be run without warnings or losing warnings because a module is used in a script that doesn't use `-w`. – Ven'Tatsu Sep 15 '10 at 17:33
  • @brian d foy: Yes, I've seen this issue on "Case-preserving but case-insensitive" file systems too. Like NTFS. :) – Robert P Sep 15 '10 at 19:39
5

Internally use pack2 ('whom'); is translated to something like

BEGIN {
    require pack2;
    pack2->import('whom');
}

Except that perl will check to see if it can call import on pack2 before it tries to call it. In your example there is no package named pack2 and so no import function to call. If your package name and file name match then perl would find the import function provided by Exporter.

There is no warning for this because Perl has a hard time telling when this was done deliberately. Most OO modules won't export any functions or variables and so they don't privide an import function.

Ven'Tatsu
  • 3,565
  • 16
  • 18
  • Thnx all it answer my Question. – Joe Sep 20 '10 at 19:28
  • I regret to say that I can only give a single +1. I've explained many times that file names and package names don't have to match, one file can contain multiple packages, one package can be spread across multiple files, etc., but never noticed that `use` and Exporter only work together properly if the file name and package name match. – Dave Sherohman Oct 29 '10 at 06:04
  • @Ven'Tatsu: If I understand you and Dave correctly, what would be the correct way to import a function from a package that is not the same as the filename? – vol7ron Jun 20 '12 at 22:29
  • @vol7ron, I would argue that while there are methods to import from a package that doesn't match it's file name, none that I can think of are correct. Sometimes functional trumps correct =) in those cases I would use `BEGIN { require 'File.pm'; Package->import('function'); }` Assuming `File.pm` is the file name, and `Package` is the package in that file. I would use the file name style of require to make it clearer that I'm not loading a "proper" Perl module. But all of that would come after figuring out why I can't just `mv File.pm Package.pm`. – Ven'Tatsu Jun 21 '12 at 13:29
  • @Ven'Tatsu: I don't use Exporter all that often, as you can tell from [my recent post here](http://stackoverflow.com/questions/11138361/perl-trouble-with-exporter/11139601). The question I started to broach was, if you have a module w/ multiple packages, how do load those other packages too? – vol7ron Jun 21 '12 at 13:51
  • @vol7ron, Ideally that should be the responsibility of the exporting package (the one that matches the file name), not the importing code. The exporting package can define it's own `sub import` that uses exporters `export_to_level` to export it's own symbols and then do the same on it's internal packages. I've left out quite a bit of technical detail that really won't fit in a comment, and it's likely not a very good design choice to have multiple packages in the same file exporting symbols. – Ven'Tatsu Jun 21 '12 at 21:21
  • @Ven'Tatsu: I agree with all the above. It's just that I think I've read perldoc all the way through, but it doesn't go into much detail about doing that - or it's possible that I've misunderstood. Anyhow, I suppose if I still care about this next week, I'll open a question. Thx for the responses – vol7ron Jun 21 '12 at 23:23
0

Got same error using module from subfolder tree without declaring full path in package.

You should write package statement with its path. For module located in subdirectory Dir write package Dir::Module; , not package Module ;. Then it works.