Kickstart has asked for the wisdom of the Perl Monks concerning the following question:

Okay, I'm lost on this...I thought I finally had the solution to using a reference to an element of an array in a foreach loop, but now I have a stranger problem. Any help would be appreciated.

In this hash I create my list of subroutines I wish to call and a descriptive name for them - they will be elements in a menu in a Perl Tk script:

my %choices = ( 'fs_sub' => 'File Systems', 'mem_sub' => 'Memory' );

Further in the script I attempt to call the list in a foreach loop:

foreach (keys(%choices)) { $choice_menu->command(-label => $choices{$_}, -activebackground => '#CCCCCC', -command => \&$_); }

All seems to work, except that the second (last) set of keys/values in the hash is repeated. Or more appropriately, the foreach loops twice on the last set, giving me:

File Systems Memory Memory
...in my menu.

Any ideas why it is doing this?

Kickstart

Replies are listed 'Best First'.
Re: perlref repeats last of array
by Zaxo (Archbishop) on Nov 26, 2001 at 12:16 UTC

    I suspect that you have have an extra key to the "Memory" value. A diagnostic print keys %choices; will tell.

    Do you realize you're using symbolic references to code? use strict; would have told you that. Here's one cure:

    my %choices = ( 'File Systems' => \&fs_sub, 'Memory' => \&mem_sub ); for (keys %choices) { $choice_menu->command( -label => $_, -activebackground => '#CCCCCC', -command => $choices{$_}); }

    Update: Your code from the reply works here without doubling the Memory line. So does the modified code I suggested. I wonder if Tk says no strict 'refs'; somewhere?

    After Compline,
    Zaxo

      I tried exactly that and I got reference errors. It's very confusing, but the code I posted works fine with 'use strict'. Here is the complete code so far. You are the second person to tell me that it won't work under use strict, but it does here.
      #!/usr/bin/perl -w use strict; use Tk; use diagnostics; # Just for testing my $wintitle = 'TkSysinfo'; my %choices = ( 'fs_sub' => 'File Systems', 'mem_sub' => 'Memory' ); my $mw = MainWindow->new; $mw->title("$wintitle"); $mw->minsize(600, 400); $mw->configure(-background => '#AAAAAA'); my $menus = $mw->Frame(-relief => 'groove', -borderwidth => 3, -background => '#EEEEEE' )->pack(-side => 'top', -fill => 'x'); my $choice_menu = $menus->Menubutton(-text => 'Choose Info', -background => '#EEEEEE', -activebackground => '#EEEEEE', -foreground => '#000000', )->pack(-side => 'left'); foreach (keys(%choices)) { $choice_menu->command(-label => $choices{$_}, -activebackground => '#CCCCCC', -command => \&$_); } # EXIT $choice_menu->separator; $choice_menu->command(-label => 'Exit', -activebackground => '#CCCCCC', -command => sub{$mw->destroy}); # Define updates to main window sub fs_sub{}; sub mem_sub{}; MainLoop;

      Kickstart

        Well, regarding our converstaion in chat about the gratuitious use of symrefs and a better way. The simplest solution is to reverse your hash:
        my %choices = ( 'File Systems' => \&fs_sub, 'Memory' => \&mem_sub ); foreach (keys(%choices)) { $choice_menu->command(-label => $_, -activebackground => '#CCCCCC', -command => %choices{$_}); }
        Now its easy to see what you are doing (providing a disptach table) and its no less code or stress.

        HTH

        Yves / DeMerphq
        --
        Have you registered your Name Space?

Re: perlref repeats last of array
by jlongino (Parson) on Nov 26, 2001 at 11:56 UTC
    I think you have an interesting problem and am curious enough to want to try some things (probably other monks as well). Please post more code for us to do some cut & paste testing.

    --Jim

      I apologize for the stupidity of this one...basically, it came down to nothing to do with Perl...I resized my editing window in the midst of an edit (from 80x24 (vt100) to 80x25 (ibm standard). A line got copied twice when the window did not properly refresh.

      Man, now I feel dumb.

      Kickstart