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

I am trying to throw something together quickly, but ran into this problem. Code is like this at this moment:

use Net::Telnet; use Tk; use Data::Dumper; use XML::Simple; use strict; use warnings; my $tasks = XMLin("command.xml"); print Dumper($tasks); my $mw = MainWindow->new(); for (0..$#{@{$tasks->{"task"}}}) { $mw->Button(text => $tasks->{"task"}->[$_]->{"description"}, c +ommand => sub {pub($_)})->pack(); } MainLoop; sub pub { my $task_id = shift; print "task id = $task_id\n"; my $t = new Net::Telnet(timeout => 10, Prompt => '[AATS1]$'); $t->open("ofgaix2"); $t->login("rpts1", "aats1"); my @lines; my $cmds = $tasks->{"task"}->[$task_id]->{"command"}; for (0..$#{@{$cmds}}) { @lines = $t->cmd($cmds->[$_]->{"string"}); print @lines; } }

The problem is that $task_id is not properly passed into the sub. All what I need is a way to identify who triggered the sub.

Thanks in advance.

By the way, there might be multiple ways to resolve it, at the same time, I am still interested in whether Tk itself provides a way to find out who trigger the action.

Replies are listed 'Best First'.
Re: Quick question about Tk(?)
by Arunbear (Prior) on Sep 24, 2004 at 16:15 UTC
    Avoid $_, and all will be well. Try this:
    use Tk; use strict; use warnings; my $mw = MainWindow->new(); for my $id (0 .. 3) { $mw->Button( text => "Button$id", command => sub { pub($id) } )->pack(); } MainLoop; sub pub { my $task_id = shift; print "task id = $task_id\n"; }

      That's right! I was about to post the same thing. Thanks very much!

Re: Quick question about Tk(?)
by BrowserUk (Patriarch) on Sep 24, 2004 at 16:33 UTC

    As JediWizard identified, using $_ as your id is the source of the problem, though his solutions aren't quite right.

    In his first example, quoting $_ won't do the trick, and in the second the quoting is unnecessary.

    You could also use your current code (with corrections:), but name the loop iterator. By naming the iterator, the sub will form a closure over the lexical and achieve the results you want.

    #! perl -slw use strict; use Tk; use Data::Dumper; use XML::Simple; use strict; use warnings; my $tasks = XMLin(<<EOS); <tasks> <task description="task1"></task> <task description="task2"></task> <task description="task3"></task> <task description="task4"></task> <task description="task5"></task> <task description="task6"></task> </tasks> EOS print Dumper($tasks); my $mw = MainWindow->new(); ## What was $#{@{$tasks->{"task"}}} all about :) for my $id ( 0 .. $#{ $tasks->{task} } ) { $mw->Button( -text => $tasks->{task}[$id]{description}, -command => sub { pub( $id ) } )->pack(); } MainLoop; sub pub { my $task_id = shift; print "task id = $task_id"; } __END__ P:\test>junk $VAR1 = { 'task' => [ { 'description' => 'task1' }, { 'description' => 'task2' }, { 'description' => 'task3' }, { 'description' => 'task4' }, { 'description' => 'task5' }, { 'description' => 'task6' } ] }; task id = 0 task id = 1 task id = 2 task id = 3 task id = 4 task id = 5

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: Quick question about Tk(?)
by JediWizard (Deacon) on Sep 24, 2004 at 16:08 UTC
    $mw->Button(text => $tasks->{"task"}->[$_]->{"description"}, command = +> sub {pub("$_")})->pack();

    Or ...

    $mw->Button(text => $tasks->{"task"}->[$_]->{"description"}, command = +> [\&pub, "$_"])->pack();

    I belive the problem is that Tk is passing you the value of $_ at the time the button is pressed, and it appears you want the value of $_ from the time the button is created.

    May the Force be with you

      Your described what I wanted, but the solution does not work. More thoughts?

        Did you try JediWizard's second method - it worked perfectly when I tried it.
Re: Quick question about Tk(?)
by qumsieh (Scribe) on Sep 24, 2004 at 17:07 UTC
    "$mw->Button(text => ..."
    Please note that use of option names without a leading dash is deprecated, and in recent Tk versions, it will completely fail. Please use:
    -text -command
    instead, to avoid problems later on.