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

I hope someone can enlighten me about a small problem I have.

I am writing a set of modules and want to use a global application configuration hash. Because some config depends on the system I run on, I thought I would use a BEGIN block to assign a config hash key based on the hostname. The BEGIN makes sure that this host dependent setup happens first.

However, in testing, I am seeing behaviour I am having trouble understanding.

If I assign a key inside the BEGIN to this global hash, I don't see it in the test program, unless no other keys are set in this global config hash.

Can someone explain this or direct me a decent explanation? I have looked at perlmod but still have trouble. This is Perl v5.10.0 on Debian Lenny.

Test program ttt.pl :

#!/usr/bin/perl -w use Test::More tests => 1; use ttt qw(get_key); my ($a,$b,$c) = get_key(); is($a,1);

This gives a test FAILURE - we get "undef" for $a, not 1 :

package ttt; use strict; use warnings; our @ISA = qw(Exporter); our @EXPORT = (); our @EXPORT_OK = qw(%config get_key); our %config = ( 'key' => [undef,undef,undef], ); BEGIN { $config{'key'} = [1,2,3]; } sub get_key { return @{$config{'key'}}; } 1;

If I replace the %config hash initialisation with just a declaration, it works. This passes ($a is 1):

package ttt; use strict; use warnings; our @ISA = qw(Exporter); our @EXPORT = (); our @EXPORT_OK = qw(%config get_key); our %config; BEGIN { $config{'key'} = [1,2,3]; } sub get_key { return @{$config{'key'}}; } 1;

Trying to understand this failure, I thought it was because the %config assignment (to "undef") happens AFTER the "BEGIN" assigns (1,2,3) - so the key value is over-written with "undef".

However ...

If I assign ANY key/value in the declaration of %config, I get an error e.g.

This also fails :

package ttt; use strict; use warnings; our @ISA = qw(Exporter); our @EXPORT = (); our @EXPORT_OK = qw(%config get_key); our %config = ( 'a' => 'test', ); BEGIN { $config{'key'} = [1,2,3]; } sub get_key { return @{$config{'key'}}; } 1;

I get :

Can't use an undefined value as an ARRAY reference at ttt.pm line 21. # Looks like your test died before it could output anything.

Every/Any config assignment has to happen inside the BEGIN. And I need to do it BEFORE the 'key' assignment i.e.

our %config; BEGIN { %config = ( 'a' => 'test' ); $config{'key'} = [1,2,3]; }

is OK

our %config; BEGIN { $config{'key'} = [1,2,3]; %config = ( 'a' => 'test' ); }

Gives an error :

Can't use an undefined value as an ARRAY reference at ttt.pm line 21.

What is happening here? Many thanks.

Alastair Sherringham

Replies are listed 'Best First'.
Re: Problem using BEGIN in module and retrieving global data from hash
by Anonymous Monk on Nov 21, 2010 at 15:15 UTC
    Direct assignment basically obliterates all previous values
    use DDS; my %f; Dump(\%f); %f = (1,2); Dump(\%f); %f = (3,4); Dump(\%f); %f = (%f, 6,6 ); Dump(\%f); __END__ $HASH1 = {}; $HASH1 = { 1 => 2 }; $HASH1 = { 3 => 4 }; $HASH1 = { 3 => 4, 6 => 6 };

      Of course ... I feel stupid now, and I'm not sure what I was thinking! But thanks for reading and answering.

      Cheers, Sherringham