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

[ID 20010105.019] UNIVERSAL inconsistencies

Thread Next
From:
root
Date:
January 5, 2001 14:19
Subject:
[ID 20010105.019] UNIVERSAL inconsistencies
Message ID:
200101051556.f05Funq04556@rt158.private.realtime.co.uk
This is a bug report for perl from pdcawley@bofh.org.uk,
generated with the help of perlbug 1.28 running under perl v5.6.0.

This is a bug report for perl from pdcawley@bofh.org.uk,
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 {
            shift;
            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
Wrong.

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

    #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

outputs:

    1. 
    2. 1
    3. 1
    


        


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=library
    severity=medium
---
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:
  Platform:
    osname=linux, osvers=2.2.17-16mdksmp, archname=i386-linux
    uname='linux debris.mandrakesoft.com 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
  Compiler:
    cc='cc', optimize='-O3 -fomit-frame-pointer -pipe -s -march=pentium -ffast-math -fexpensive-optimizations', gccversion=2.95.3 19991030 (prerelease)
    cppflags='-fno-strict-aliasing'
    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/libc-2.1.3.so, so=so, useshrplib=true, libperl=libperl.so
  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:
    /usr/lib/perl5/5.6.0/i386-linux
    /usr/lib/perl5/5.6.0
    /usr/lib/perl5/site_perl/5.6.0/i386-linux
    /usr/lib/perl5/site_perl/5.6.0
    /usr/lib/perl5/site_perl
    .

---
Environment for perl v5.6.0:
    HOME=/home/pdcawley
    LANG=en
    LANGUAGE=en_GB:en
    LC_COLLATE=en_GB
    LC_CTYPE=en_GB
    LC_MESSAGES=en_GB
    LC_MONETARY=en_GB
    LC_NUMERIC=en_GB
    LC_TIME=en_GB
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/pdcawley/pub/i686-pc-linux-gnu/bin:/home/pdcawley/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games:/home/pdcawley/bin
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh
---
Flags:
    category=library
    severity=medium
---
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:
  Platform:
    osname=linux, osvers=2.2.17-16mdksmp, archname=i386-linux
    uname='linux debris.mandrakesoft.com 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
  Compiler:
    cc='cc', optimize='-O3 -fomit-frame-pointer -pipe -s -march=pentium -ffast-math -fexpensive-optimizations', gccversion=2.95.3 19991030 (prerelease)
    cppflags='-fno-strict-aliasing'
    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/libc-2.1.3.so, so=so, useshrplib=true, libperl=libperl.so
  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:
    /usr/lib/perl5/5.6.0/i386-linux
    /usr/lib/perl5/5.6.0
    /usr/lib/perl5/site_perl/5.6.0/i386-linux
    /usr/lib/perl5/site_perl/5.6.0
    /usr/lib/perl5/site_perl
    .

---
Environment for perl v5.6.0:
    HOME=/home/pdcawley
    LANG=en
    LANGUAGE=en_GB:en
    LC_COLLATE=en_GB
    LC_CTYPE=en_GB
    LC_MESSAGES=en_GB
    LC_MONETARY=en_GB
    LC_NUMERIC=en_GB
    LC_TIME=en_GB
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/pdcawley/pub/i686-pc-linux-gnu/bin:/home/pdcawley/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games:/home/pdcawley/bin
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About