### part 1: a package that ties a scalar and spews debugging stuff

package Tied;
use strict;

sub TIESCALAR { warn "TIESCALAR @_\n";  my $x = $_[1]; bless \$x, $_[0]; }
sub FETCH     { warn "<${$_[0]}> FETCH @_\n"; 0; }
sub STORE     { warn "<${$_[0]}> STORE @_\n"; }

### part 2: two identical packages that exports $!

package Bang;
use strict;
use vars qw(@ISA @EXPORT);
require Exporter;
@ISA = qw(Exporter);
@EXPORT    = qw( $! );

use vars qw( $tied );

tie $tied, 'Tied', 'in Bang';
$Bang::{'!'} = $Bang::{'tied'};


package Boing;
use strict;
use vars qw(@ISA @EXPORT);
require Exporter;
@ISA = qw(Exporter);
@EXPORT    = qw( $! );

use vars qw( $tied );

tie $tied, 'Tied', 'in Boing';
$Boing::{'!'} = $Boing::{'tied'};

### part 3: try with main

package main;
Bang->import();
print "[$!]\n";

### part 4: try someplace else

package Somewhere;
Boing->import();
print "[$!]\n";

### Conclusion: $! in a package always gets you $::!
