in reply to while loop question

Hello adriang,

I realise your code snippet is just for illustration; still, it may be instructive to note its various problems:

  1. while ( my $key=keys(%hash) {

    Compile error: the second closing parenthesis is missing.

  2. my $key=keys(%hash)

    Logic error: in scalar context the keys function returns the number of keys in the hash, not the keys themselves. You need a for loop here:

    for my $key (keys %hash) {
  3. keys %hash

    Logic error: since you want to exit the loop when a certain key is reached, the behaviour of the code depends on the order in which the keys are returned; but this order is “apparently random” (keys). To get deterministic behaviour, you need to sort the keys. For example:

    for my $key (sort keys %hash) {
  4. }  $hash{$key}=$verb;

    Compile error: if you’re running under use strict; (and you should be!), you will see this error message:

    Global symbol "$key" requires explicit package name at ...

    You could fix this1 by declaring my $key; before the loop, but it’s better style to restrict the scope of this lexical variable:

    for my $key (sort keys %hash) { if ($key eq $verb) { $hash{$key} = $verb; last; } }

Update (Aug 23):
1That is, you could fix the error message. But the code still wouldn’t work correctly, because $key is a temporary alias within the foreach loop (see “alias” in perlglossary), and it reverts to its pre-loop value when the loop ends.

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: while loop question
by adriang (Sexton) on Aug 21, 2014 at 10:51 UTC

    Thanks for the quick answer. nr.1 - copy-paste error. nr.2 - 100% RIGHT. nr.3 - understand. nr.4 - fast writing error :-) Sorry, code nr.4 is not good for "since you want to exit the loop when a certain key is reached" because I want to create a hash element if the has key is not there. For now I use the "defined" function (below) to do the work but I realy want to know if there is other solution.

    unless ( defined $email{"email"} ) { $email{$html->param("email")}=$html->param("name"); }
      exists should help you with this problem. As you may have noticed, looping over keys of a hash is much slower than accessing it by key. By the way, very often it is plain wrong.

        "exisys" is not good for me at leat for this crrent problem because I use AnyDBM_File:

        AnyDBM_File doesn't define an EXISTS method at /gd/Development/Perl/Pr +actice/www/cgi-bin/submitcoffee.pl line 32.