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

OK, now I know the answer is almost always "No!", but I'm at the end of my tether, and short of diving down into C code, I can't take it any further.

I'm using perl, v5.8.0 built for i386-linux-thread-multi.

Essentially it seems that UNIVERSAL::isa, my favourite swiss army knife function, is behaving weirdly. Here is the most simple example I can boil it down to.
Loading DB routines from perl5db.pl version 1.19 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(-e:1): 1 DB<1> $Foo::VERSION = 1; DB<2> sub Foo::new { bless {}, shift } DB<3> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 1 DB<4> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 1 DB<5> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 1 DB<6> @Foo::ISA = (); DB<7> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 1 DB<8> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 '' DB<9> x UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ); 0 '' DB<10>
The particular problem I have with this situation is that, if your class doesn't have an @ISA, lots of things ( overload and Carp::croak for example), accidentally set @SomeClass::ISA to (), when doing things like this

Example from overload::mycan
foreach $p (@{$package . "::ISA"}) {

This breaks my usual "is this an object of some sort" test of UNIVERSAL::isa( ref $Object, 'UNIVERSAL' ).

What do you all think?

Replies are listed 'Best First'.
Re: Have I found a bug in Perl?
by chromatic (Archbishop) on Jan 11, 2004 at 07:17 UTC

    Perhaps Scalar::Util's blessed() is a better check for objectness.

    I ran the following code and all tests pass under Perl 5.8.2. Odd.

    #!/usr/bin/perl -w use strict; package Foo; use strict; use vars '$VERSION'; $VERSION = 1; package main; use Test::More tests => 4; my $foo = bless {}, 'Foo'; isa_ok( $foo, 'UNIVERSAL' ); ok( UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) ); @Foo::ISA = (); isa_ok( $foo, 'UNIVERSAL' ); ok( UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) );
      The _first_ UNIVERSAL::isa after setting @Foo::ISA does work... it only starts breaking when you call the function 2-4 times.

      That's what bugs me the most, the multiple successive invocations of the same command return different values.
Re: Have I found a bug in Perl?
by ysth (Canon) on Jan 11, 2004 at 07:14 UTC
    First of all, for an interactive perl I prefer perl -wlne'eval;print$@if$@' to using the debugger.

    I do see this behaviour under 5.6.2 but not 5.8.2.What version are you using?

    Update: I see the v5.8.0 now, somehow I missed it before.

    Update: this is fixed in 5.8.1, see bug #3284. Fixed by Dave Mitchell in patch #20168.

      The behaviour is not interactive mode specific...

      #!/usr/bin/perl -w use strict; print "Setting \@Foo::ISA = ()\n"; @Foo::ISA = (); print "UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == '" . UNIVERSAL::isa( 'F +oo', 'UNIVERSAL' ) . "'\n"; print "UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == '" . UNIVERSAL::isa( 'F +oo', 'UNIVERSAL' ) . "'\n"; print "UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == '" . UNIVERSAL::isa( 'F +oo', 'UNIVERSAL' ) . "'\n"; exit(); ... resulting in ... Setting @Foo::ISA = () UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == '1' UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == '' UNIVERSAL::isa( 'Foo', 'UNIVERSAL' ) == ''

      On the other matter, I'm aware things work slightly differently in the debugger, but I use it for things like the 'x' command and other stuff...
Re: Have I found a bug in Perl?
by Aristotle (Chancellor) on Jan 11, 2004 at 15:13 UTC
    Issue at hand aside, as it has been resolved, when I want to test for objectness I prefer
    UNIVERSAL::can( $foo, 'can' );

    Makeshifts last the longest.

      That's how Template Toolkit does it. Seems to work well.
Re: Have I found a bug in Perl?
by perrin (Chancellor) on Jan 11, 2004 at 18:48 UTC
    Yes, it's a bug. I reported this a long time ago and was told it was a side-effect of some optimization. It may be fixed by now, but I haven't tried on the latest releases.