develooper Front page | perl.perl5.porters | Postings from January 2001

[ID 20010108.001] UNIVERSAL inconsistencies

January 8, 2001 01:02
[ID 20010108.001] UNIVERSAL inconsistencies
Message ID:
This is a bug report for perl from,
generated with the help of perlbug 1.28 running under perl v5.6.0.

[Please enter your report here]

I've been mucking around with container classes in an application
here. What I want to be able to do is to have my container masquerade
as the thing it contains (aka a Decorator if you do the pattern
language stuff)

Aha! I thought, I can just do this:

    sub isa {
        my($self, $class) = @_;
        $self->SUPER::isa($class) ||
            ref($self) && eval {$self->item->isa($class)};

    sub can {
        my($self, $method) = @_;
        my $can = $self->SUPER::can($method);
        return $can if $can;
        $can = ref($self) && eval {$self->item->can($method)};
        return unless $can;
        return sub {
            return $can->($self->item,@_);

    sub AUTOLOAD {
        my $method = $AUTOLOAD;
        $method =~ s/.*:://;
        return if $method eq 'DESTROY';
        my $self = shift;
        return eval {item->can($method)} ? $self->item->$method(@_) 
            : $self->${\("SUPER::$method")}(@_);

Which, whilst not being exactly easy, isn't really rocket science
either, and I would argue that (admittedly via a mechanism other than
@ISA) this object inherits from both its own @ISA tree and from the
package of the object that it contains. And hey, if there's more than
one way to do it, there can surely be more than one way to inherit.

And it works, with one (depressingly large) caveat: It doesn't work if
any client code uses UNIVERSAL::isa directly.

Aha! I'll just overload UNIVERSAL::isa and UNIVERSAL::can then. Well,
yeah, but the reason for using Container::isa and Container::can was
that I didn't want to do anything quite so drastic.

Ideally, I want the UNIVERSAL 'isa' and 'can' to check at each step up
the inheritance tree if there's a 'local' implementation at that level
that isn't the UNIVERSAL one, and if there is, to stop walking any
further up that branch of the tree and see what the local
implementation says. I can do this in Perl, and I will if I have to,
but it's not going to be anything approaching fast and I'm afraid I
don't have the C skills to supply a patch.

Yes, I know there are other ways to do this without having to roll a
bunch of specialist container classes but they all involve rather more
messing with the symbol table than I like, along with a requirement to
rebless the container every time its contents change, which just seems

Also, while investigating this I came across the following piece of
weirdness, which seems to run contrary to the documentation of

    #perl -l
    print '1. ', UNIVERSAL::isa('Foo', 'UNIVERSAL'); # Expect 1
    print '2. ', Foo->isa('UNIVERSAL');              # Expect 1
    print '3. ', UNIVERSAL::isa('Foo', 'UNIVERSAL')  # Expect 1


    2. 1
    3. 1


[Please do not change anything below this line]
Site configuration information for perl v5.6.0:

Configured by flepied at Sat Sep 30 18:19:36 CEST 2000.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration:
    osname=linux, osvers=2.2.17-16mdksmp, archname=i386-linux
    uname='linux 2.2.17-16mdksmp #1 smp thu sep 28 15:25:49 cest 2000 i686 unknown '
    config_args='-des -Darchname=i386-linux -Dd_dosuid -Ud_csh -Duseshrplib -Doptimize=-O3 -fomit-frame-pointer -pipe -s -march=pentium -ffast-math -fexpensive-optimizations -Dprefix=/usr -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/lib/perl5/man/man3'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=undef d_sfio=undef uselargefiles=define 
    use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef
    cc='cc', optimize='-O3 -fomit-frame-pointer -pipe -s -march=pentium -ffast-math -fexpensive-optimizations', gccversion=2.95.3 19991030 (prerelease)
    ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    stdchar='char', d_stdstdio=define, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lposix -lcrypt
    libc=/lib/, so=so, useshrplib=true,
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.6.0/i386-linux/CORE'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:

@INC for perl v5.6.0:

Environment for perl v5.6.0:
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About