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

Hello!

I am using perk/tk here and am having issues creating a file menu and having it perform a specific action based on a directory search.

----------

So previously I had the commands hard-coded and it looked like this:

$menubar = $top->Menu; $file_menu = $menubar->cascade(-label => "~File"); $file_menu->command(-label => "Restart", -command => \&Restart); $file_menu->command(-label => "Exit", -command => \&Exit); $file_menu = $menubar->cascade(-label => "Filter"); $file_menu->command(-label => "All", -command => sub {$fname = "mac +hines"; &Restart}); $file_menu->command(-label => "HP-UX", -command => sub {$fname = "m +achines.HPUX"; &Restart}); $file_menu->command(-label => "Linux", -command => sub {$fname = "m +achines.Linux"; &Restart});

----------------

But have since decided to pull the list (HP-UX, Linux, other things in the future), from files found in a directory. So now my code looks like this:

# Get filter list my @filter = qw(); my $dir = '.'; my $x=0; opendir(DIR, $dir) or die $!; while (my $file = readdir(DIR)) { next unless (-f "$dir/$file"); next unless ($file =~ m/^machines\./); push (@filter, $file); } closedir(DIR); $file_menu = $menubar->cascade(-label => "~File"); $file_menu->command(-label => "Restart", -command => \&Restart); $file_menu->command(-label => "Exit", -command => \&Exit); $file_menu = $menubar->cascade(-label => "Filter"); $file_menu->command(-label => "All", -command => sub {$fname = "mac +hines"; &Restart}); foreach (@filter) { $file_menu->command(-label => "$_", -command => sub {$fname = "$_ +"; &Restart}); }

------------------

However the issues lies in that when the button is clicked, "$fname" no longer knows what "$_" is, or is null.

So my question is, how can I create a file menu based on an array but still be able to set a variable in the command portion of the menu command?

I hope that all makes sense!

Replies are listed 'Best First'.
Re: Perl/Tk menu and commands based on array
by tybalt89 (Monsignor) on Feb 10, 2017 at 14:03 UTC

    try:

    foreach my $item (@filter) { $file_menu->command(-label => $item, -command => sub {$fname = $i +tem; &Restart});

    it's a closure thing

      Thank you very much!!! I knew there was something wrong with my logic but I am not familiar enough with perl to know how to structure it properly. Thanks :)
Re: Perl/Tk menu and commands based on array
by haukex (Archbishop) on Feb 11, 2017 at 11:12 UTC

    Hi richie,

    Just to expand briefly on what tybalt89 mentioned: In Perl, closures like "sub {$fname = "$_"; &Restart}" in your code only "close over" lexicals (defined with my), and not global/package variables, that is those defined with our, or many of the special variables. $_ is one of those special variables that is a global. Whenever sub {$fname = "$_"} is executed, it will access the current value of $_.

    Hope this helps,
    -- Hauke D