0

I have prepared a short loop that looks like this:

@array = ("a", "b", "c", "d", "e");
$count=0;
print "@array\n";
foreach $string(@array){
    $number=$count++ +1 ;
    $string{$link} = $number;
    print "$string\n$string{$link}\n";
}

It should come out as

a
1
b
2

... and so on. It works but when I print it out on the terminal, I get warning messages:

Use of uninitialized value $link in hash element at ./hashing_an_array.pl line 11.
Use of uninitialized value $link in hash element at ./hashing_an_array.pl line 12.
a
1
Use of uninitialized value $link in hash element at ./hashing_an_array.pl line 11.
Use of uninitialized value $link in hash element at ./hashing_an_array.pl line 12.
b
2

...

etc

Why do I get these messages? I just wanted to know so that even though it works, I am sure I know what I am doing.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Aletia
  • 89
  • 5
  • 6
    `use strict;` would have told you that the variable `$link` is never defined. From your code I'm guessing you wanted to bind each element of `@array` to `$link` in turn, so try with `for my $link (@array) { ... }` instead – Botje Aug 20 '19 at 10:03
  • 1
    Unrelated: `$count++ + 1` is equivalent to `++$count`. – Botje Aug 20 '19 at 10:06
  • so $link is undefined, which in context of requiring a string as a key in the hashref, perl interprets as empty string. Therefore, on each iteration of the loop, it stores the current value in the hashref at key `''`. Because it's quite likely that this is unintentional, perl also emits a warning that it has done that. You'll end up with a hashref with one key (`''`) and the latest value put there. – bytepusher Aug 22 '19 at 14:38

2 Answers2

2

It happens because you never assigned a value to $link so it's default value is undef. Trying to use undef as a hash key generates a warning message because it's invalid.

Read perldata http://perldoc.perl.org/perldata.html

lordadmira
  • 1,807
  • 5
  • 14
2

As noted in the other answers $link is undeclared and you should use strict; which would tell you this:

Global symbol "$link" requires explicit package name (did you forget to declare "my $link"?)

The following snippet is probably something like what you were after:

#!/usr/bin/perl

use strict;
use warnings;

my @array = qw(a b c d e);

my $count = 0;

my %link;

foreach my $string (@array) {
    $count++;
    $link{$string} = $count;
    print "$string\n";
    print "$link{$string}\n";
}

Although you should probably rename your hash and iteration variable to something that better reflects your intent, like for example using %count_for and $letter if you were doing letter counts.

htaccess
  • 2,800
  • 26
  • 31
  • Alternative explanation: `$string{$link}` was supposed to be `$link{$string}`, which would fit with the loop variable being `$string`. – melpomene Aug 25 '19 at 22:23
  • True, but I think using descriptive names like `%count_for` and `$letter` is the real solution :) – htaccess Aug 25 '19 at 22:28
  • Descriptive, but misleading, since `%count_for` doesn't really store word counts. In fact, the code as given doesn't need a hash at all. – melpomene Aug 25 '19 at 22:29
  • Yea well I don't really get the intent of what the op is doing here. We could obviously play golf and reduce this to almost nothing. All I know is he is storing a number in association with a letter of the alphabet, so perhaps `%position_in_alphabet` and `$index` ... The point is to use best practices around variable and hash names such that the names make the intent clear. – htaccess Aug 25 '19 at 22:38
  • But yea I think I will change it to your suggestion, its probably more like what was intended. – htaccess Aug 25 '19 at 22:41