Use of uninitialized value in concatenation (.) or string

S

S

Hi,

In advance sorry for the lengthy email. I'm new at using Perl and I have
never posted here so my goal is to hopefully provide as much information as
neccessary. I provided:
- a broken test script exhibiting a problem (along with the output)
- a fixed test script no longer exhibiting the problem (along with the
output)
- a quick description of my environment
- a list of what I tried

One could wonder why I'm posting here since I already have 'a fix'. Well, I
would like to understand why moving this specific line of code fixed the
problem. Specifically, I want to understand why it seems that a 'hash' can
be alternatively 'initialized' or 'uninitialized' in the broken script. It
just does not make sense to me with my limited knowledge.


In my example, assuming that %messages turned out to be a very big hash,
what would be the impact of rebuilding the @sortedmessages array every time
in the loop as I'm doing in the 'fixed' test script? Yes, I know that it
sounds like I want to optimize before I even know how to code. Here again,
it is just for my own 'edification'. Thanks for reading the rest of the mail
and teaching me along.

Note 1: the script is written for learning purpose only, you are welcome to
comment on it also.
Note 2: English is not my native language and I'm trying really hard to be
understood on this forum. :)


The test script exhibiting a problem:
=========================
use strict;
use warnings;
my %messages;
$messages{"C"}="333";
$messages{"B"}="222";
$messages{"A"}="111";
my @sortedmessages = map { { ($_ => $messages{$_}) } } sort keys %messages;
my $maxi=2;
my $message_element;
my $key = my $value;
foreach my $i (0...$maxi)
{
foreach $message_element (@sortedmessages)
{
($key, $value) = each %$message_element;
print ("key is $key and value is $value\n");
}
}


Output with the broken script:
=====================
key is A and value is 111
key is B and value is 222
key is C and value is 333
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
key is and value is
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
key is and value is
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
Use of uninitialized value in concatenation (.) or string at
D:\test.pl line 16.
key is and value is
key is A and value is 111
key is B and value is 222
key is C and value is 333


The 'fixed' test script no longer exhibiting a problem
=====================================
use strict;
use warnings;
my %messages;
$messages{"C"}="333";
$messages{"B"}="222";
$messages{"A"}="111";
my $maxi=2;
my $message_element;
my $key = my $value;
foreach my $i (0...$maxi)
{
#line 7 from broken script was moved here and fixed the problem
my @sortedmessages = map { { ($_ => $messages{$_}) } } sort keys
%messages;
foreach $message_element (@sortedmessages)
{
($key, $value) = each %$message_element;
print ("key is $key and value is $value\n");
}
}

Output with fixed script:
=====================
key is A and value is 111
key is B and value is 222
key is C and value is 333
key is A and value is 111
key is B and value is 222
key is C and value is 333
key is A and value is 111
key is B and value is 222
key is C and value is 333


Current environment:
==============
ActiveState Perl v5.8.0 built for MSWin32-x86-multi-thread (build 806) under
Win2K.

What I tried:
=========
- searched on Google
- looked at the Perl documentation locally available
- ran the script Open_Perl_IDE\PerlIDE.exe ( I don't seem able to reproduce
this problem with that debugger or maybe I don't know how to use it. :)
 
G

Gunnar Hjalmarsson

S said:
Specifically, I want to understand why it seems that a 'hash' can
be alternatively 'initialized' or 'uninitialized' in the broken
script.

You have probably not understood how the each() function works. Please
study the documentation for it:

http://www.perldoc.com/perl5.8.0/pod/func/each.html

If you just skip the redundant use of each() in your "broken" script,
it will work as expected:

($key, $value) = %$message_element;

HTH
 
S

S

Indeed I had not understood this aspect of each during my first reading.

Thank you for the pointer.
S
 
G

Gunnar Hjalmarsson

Since this was your first post here, I'd like to make a couple of
additional comments besides the pointer to what caused the unexpected
behaviour.
In advance sorry for the lengthy email. I'm new at using Perl and I
have never posted here so my goal is to hopefully provide as much
information as neccessary. I provided:
- a broken test script exhibiting a problem (along with the output)
- a fixed test script no longer exhibiting the problem (along with
the output)
- a quick description of my environment
- a list of what I tried

Don't be sorry. Your post was very good. Yes, there was a lot of info
that proved to be redundant, but bottom line is that the info you
provided made it easy to help.
One could wonder why I'm posting here since I already have 'a fix'.
Well, I would like to understand why moving this specific line of
code fixed the problem. Specifically, I want to understand why it
seems that a 'hash' can be alternatively 'initialized' or
'uninitialized' in the broken script. It just does not make sense
to me with my limited knowledge.

Great! That's the right attitude to programming. Don't be content only
because something "works" if you don't understand *why* it works.
In my example, assuming that %messages turned out to be a very big
hash, what would be the impact of rebuilding the @sortedmessages
array every time in the loop as I'm doing in the 'fixed' test
script?

Well, now you know that that is not necessary, so there is no reason
to find out...
Note 2: English is not my native language and I'm trying really
hard to be understood on this forum. :)

You do very well. It's not my native language either. Guess 'they'
have to stand it. :)
use strict;
use warnings;

Glad to see that you had enabled both strictures and warnings in your
first scripts here.
my %messages;
$messages{"C"}="333";
$messages{"B"}="222";
$messages{"A"}="111";
my @sortedmessages = map { { ($_ => $messages{$_}) } } sort keys %messages;

It's unnecessary to create an array of hashes here. An array of arrays
should be sufficient:

my @sortedmessages =
map { [ ($_ => $messages{$_}) ] } sort keys %messages;
------------^-----------------------^
my $maxi=2;
my $message_element;
my $key = my $value;

No need to declare $key and $value separately here.
foreach my $i (0...$maxi)
{
foreach $message_element (@sortedmessages)
{
($key, $value) = each %$message_element;

Assuming an array of arrays:

my ($key, $value) = @$message_element;
----^^
(can be declared here instead)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top