views:

54

answers:

3

I find it a bit weird that I have to wrap defined subroutines anonymously when specifying the -command argument for Tkx widgets.

An excerpt from a TkDocs tutorial demonstrates this:

my $cb = $frm->new_ttk__button ( -text => "Calculate",
                                 -command => sub {calculate();}  );

sub calculate {
   $meters = int(0.3048*$feet*10000.0+.5)/10000.0 || '';
}

Why doesn't it work when I write -command => &calculate() or -command => \&calculate()?

+1  A: 

It should work with -command => \&calculate. Note the lack of parentheses.

The examples you gave are actually executing the subroutine and assigning the value returned by it to the -command key.

For more info see perlsub and perlref

kixx
Nope. It doesn't execute, with or without the parens.
Zaid
It would've been ridiculous to see `\%calculate` work without parentheses. What if I needed to pass arguments to it?
Zaid
Zaid
+2  A: 

You don't have the syntax quite right. Your examples call the subroutine (the & bypasses any prototypes) and passes either the return value (&calculate()) or a reference to it (\&calculate()) to the -command option. You want to assign a reference to the subroutine itself, which you can do via:

-command => \&calculate

Note the lack of trailing parentheses. Also note that you can't pass arguments this way. If you want to do that you need to either wrap the call in an anonymous subroutine:

-command => sub { calculate(12) }

or pass the option an ARRAY reference instead of a CODE reference:

-command => [\&calculate, 12]

There's a subtle difference between the two forms that's important if you use a variable instead of a literal value.

-command => sub { calculate($x) }  # creates a closure over $x
-command => [\&calculate, $x]      # makes a copy of $x

Using the first form changes to $x will be visible when the command is invoked. Under the second form they won't be; each invocation will see the value at the moment the binding was created. Both forms are useful; you just need to exercise good judgment when deciding which to use.

Michael Carman
Zaid
Michael Carman
Zaid
+1  A: 

Zaid said, "I'm enlightened. But I still don't see why the \&calculate syntax doesn't work with me... – Zaid 24 mins ago"

Zaid, the \&calculate syntax does work. You were trying to use the \&calculate() syntax. The first binds to "a reference to the subroutine calculate to be run later", the latter binds as "a reference to (the return value of a call calculate with no arguments, and bypassing argument prototypes ).

Do you have a longer, compilable code snippet that we can use for testing/analysis? I am not recently familiar with TK.

spazm
Zaid