Find the Bug! (Because I can't)

Ovid on 2008-04-22T10:42:43

I really get tired of needing compile time assignments for mutable values. I can't use a constant, so I'm forced to do stuff like this:

my @exception_types;
BEGIN {
    @exception_types = qw(unused no_title tickles);
}

That gets tedious, so I was trying for a syntax like this:

use var \my @exception_types = qw(unused no_title tickles);
foreach my $type (@exception_types) { ... }

With this code to drive it:

package var;

use strict;
use warnings;
use Scalar::Util 'reftype';
use Carp 'croak';

sub import {
    my $class = shift;
    my $num_vals = @_ - 1;
    my $reftype = reftype $_[0] || '';
    if (!$reftype) {
        ${ $_[0] } = $_[1];
    }
    elsif ( 'ARRAY' eq $reftype ) {
        @{ $_[0] }= @_[ 1..$#_ ];
    }
    elsif ( 'HASH' eq $reftype ) {
        %{ $_[0] }= @_[ 1..$#_ ];
    }
    else {
        croak "var cannot handle ($reftype)";
    }
}

1;

But I keep getting this error if I try to use that variable:

Global symbol "@foo" requires explicit package name at ...

B::Deparse is no help:

Global symbol "@foo" requires explicit package name at foo.pl line 9.
foo.pl had compilation errors.
While deparsing foo.pl near line 9,
Can't locate object method "ARRAY" via package "B::PV" at /opt/csw/lib/perl/5.8.8/B/Deparse.pm line 2815.
CHECK failed--call queue aborted at foo.pl line 9.

Is this just not possible? Maybe some PadWalker magic ...


my guess

rjbs on 2008-04-22T11:24:06

First off: I think you mean s/@foo/@exception_types/ in your error messages and a fat arrow rather than an = in your use statement.

I ran into this problem when developing Sub::Exporter. It lets you say:

my $sub;
use Thing::ThatExports exported_routing => \$sub;
...and the coderef goes into the scalar instead of your symbol table. This never worked:

exporting_routine => \my $sub;
My assumption is that it's because of this equivalency:

use Foo bar => $baz;
 
BEGIN {
  require Foo;
  Foo->import(bar => $baz);
}
The Secret Begin Block (tm) seems to have an invisible scope. Just like the Phil Collins song.

Re:my guess

Ovid on 2008-04-22T12:25:37

Yeah, I was getting a bit sloppy in the post. Thanks for pointing those out.

I've tried using PadWalker to get around some of these issues, but no love. Damn.

"via some slightly insane perlguts magic"

Aristotle on 2008-04-23T05:07:52

use Devel::BeginLift qw( init_var );

sub init_var(\[$%@];@) {
    my $var = shift;
    if    ( 'ARRAY' eq ref $var ) { @$var = @_ }
    elsif ( 'HASH'  eq ref $var ) { %$var = @_ }
    else                          { $$var = $_[0] }
    return;
}

init_var my @foo => qw/ bar baz /;

BEGIN { print "@foo\n" }

=begin output

bar baz

Re:"via some slightly insane perlguts magic"

Ovid on 2008-04-23T07:36:04

Beautiful! Mind if I clean this up and post it to the CPAN? (Or you can since you posted the code. Seems unfair to steal it from you :)

Re:"via some slightly insane perlguts magic"

Aristotle on 2008-05-22T06:53:30

I was going to, but it’s obviously not going to happen, so if you want to go ahead, then do.

Re:"via some slightly insane perlguts magic"

Ovid on 2008-05-22T07:55:17

Heh. I'm heading on holiday for over a week. I doubt I'm going to get around to it, either :)