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

#!/usr/bin/perl package one; use Class::Spiffy -base; our @EXPORT = qw(function); sub function { print "Function in package one\n" } package two; @two::ISA = qw(one); print STDERR "Class::Spiffy version is ", $Class::Spiffy::VERSION, "\n +"; print STDERR "Can two function? ",two->can('function'), "\n"; function(); __END__ cd /home/henry/dev/ /usr/bin/perl -w /home/henry/dev/spiffy_bug.pl Class::Spiffy version is 0.15 Can two function? CODE(0x814b738) Undefined subroutine &two::function called at /home/henry/dev/spiffy_b +ug.pl line 12. Compilation exited abnormally with code 255 at Mon Feb 20 13:34:34

Replies are listed 'Best First'.
Re: This can't happen, can it?
by blokhead (Monsignor) on Feb 20, 2006 at 20:57 UTC
    Inheritance/@ISA only comes into play for method calls. function() by itself is not a method call. To make it one, say something like two->function (a class method call).

    If you're looking for similar behavior without using method calls, you don't want inheritance at all. You should have the one package export function, i.e.,

    package one; use base 'Exporter'; @EXPORT_OK = qw[ function ]; sub function { ... } package two; use one 'function'; function();
    Update: It's come to my attention that Spiffy supposedly exports things anyway. So I'm not sure what the problem is (since it clearly doesn't get exported in this example).

    blokhead

Re: This can't happen, can it?
by Corion (Patriarch) on Feb 20, 2006 at 21:06 UTC

    Spiffy does weird things like source filtering and adding magic re-exporting to your code, which firstly makes your Perl look like Perl but behave really different, and secondly doesn't seem to work correctly. My guess is that the source filtering does not kick in for package two or is still active, even though you only "requested" it for package one. Try putting the two packages into separate files, or better, stay away from Spiffy.

    I just now realized that you're using Class::Spiffy, which supposedly does not do source filtering, so I guess that just the exporting in Class::Spiffy messes up things. Try putting your packages into separate files to see if that improves things.

    A third update: blokhead was initially correct. Setting @ISA does not import the stuff, or shouldn't. So you only get inheritance, but you don't get the magic Spiffy auto-exporting of functions.

      Well, what makes me think it might be a perl bug is the fact that two->can('function') returns true, in other words, package two DOES know how to 'function', yet on the very next line, after calling function(), we get:
      Undefined subroutine &two::function called at /home/henry/dev/spiffy_bug.pl line 12.

      So how can a package return true to -->can('function') and yet it can't execute function? It seems to me that that can't happen?

      Best wishes,
      Henry Laxen

        So how can a package return true to -->can('function') and yet it can't execute function? It seems to me that that can't happen?
        The same way that you can call 411 and get Joe Blow's phone number, and it automatically put you through, only to get "This number is no longer in service". That is, the can lookup doesn't jive with the execution mechanism.

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

        Because can (in class form) does respect inheritance, while a fully specified function name (like foo::bar) does not respect inheritance. Look at the following reduced code:

        package Parent; sub foo { print "foo in parent(@_)\n"; }; sub bar { print "bar in parent(@_)\n"; }; package Child; @ISA = qw(Parent); sub foo { print "foo in child(@_)\n"; }; package main; eval { Child::foo(); }; warn $@ if $@; eval { Child->foo(); }; warn $@ if $@; eval { Child::bar(); }; warn $@ if $@; eval { Child->bar(); }; warn $@ if $@;
Re: This can't happen, can it?
by chromatic (Archbishop) on Feb 21, 2006 at 01:54 UTC
    use subs 'foo'; sub bar; foo(); bar();