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


In reply to Problem using BEGIN in module and retrieving global data from hash by sherr

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.