[Israel.pm] Correct way of taking a slice of a hash reference

Yitzchak Scott-Thoennes sthoenna at efn.org
Mon Jan 21 01:14:15 PST 2008

On Mon, Jan 21, 2008 at 10:59:52AM +0200, Peter Gordon wrote:
> This is a bit off topic - but anyway ....

Seems on topic to me?

> Can someone explain, what appears to me to be bizarre behaviour.
> Normally, Perl won't produce runtime fatal errors if the syntax is
> correct.

Yes, it does; all the time.  Particularly with references.

> Why can't the two lines marked below just return undef.

I'd expect an empty list, if anything.  undef would be very wrong.

> The failure on @$q is particularly irritating. If a reference to an
> array is passed and the value happens to be undef because there were no
> entries, you need to either check that the value is a reference to an
> array, or to do an eval. Good programming practice would say the the
> original value should be initialized correctly. But I would prefer Perl
> to just me undef.
> And if you are going to argue that this is correct behaviour, then why
> does $s->{aaa} and co work?
> use strict ;
> my $s ;
> my @t = %$s ; # <-- This causes a fatal error
> my $t1 = $s->{aaa} ; # This works
> my $q ;
> my @w = @$q ; <-- This causes a fatal error
> my $t2 = $q->[10] ; # This works

Basically, some ways of using a reference will promote ("vivify")
undef to a reference of the correct type, and some will not.
Mostly, the division is in whether you are potentially modifying
the referred-to structure or not.  Specifying a hash key or array
index potentially creates it, so counts as modifying (even though
in the simple case you show, no modification would take place,
element dereferencing in general *may* modify).

You can just initialize your variable to start with:

my $s = {};
my $q = [];

or check if it is undef and, if so, provide a suitable empty hash or

my @t = %{$s || {}};
my @w = @{$q || []};

or even initialize it on the fly:

my @t = %{$s ||= {}};
my @w = @{$q

More information about the Perl mailing list