开发者

giving a reference to a function in another module in Perl

开发者 https://www.devze.com 2023-04-02 15:06 出处:网络
I want to make a small GUI using Tk in Perl that will have 2 buttons: Race and Quit. I want the Race button to run a function that is located in a module Car and is called Race.

I want to make a small GUI using Tk in Perl that will have 2 buttons: Race and Quit.

I want the Race button to run a function that is located in a module Car and is called Race.

I've written the following code:

#!/usr/bin/perl -w

use strict;
use warnings;
use Car;
use Tk;

my $mw = MainWindow->new;
$mw->Label(-text => "The Amazing Race")->pack;
$mw->Button(
        -text    => 'Ra开发者_运维百科ce',
        -command => sub {Car->Race()},
)->pack;
$mw->Button(
        -text    => 'Quit',
        -command => sub { exit },
)->pack;
MainLoop;

It works, but It seems stupid to me to make an unnamed subroutine that will just call another subroutine. But when I tried to use -command => sub Car->Race(), or -command => sub \&Car->Race(), it didn't work.

I understand that this is because I'm not passing a reference to the function. How do I pass a reference to a function that is located in another namespace (module)?


Car->Race()

is the same* as

Car->can('Race')->('Car');
^^^^^^^^^^^^^^^^   ^^^^^
sub ref            args

As you can see, an argument is passed to the sub. If you don't want to use an anon sub, you'll have to instruct Tk to pass that argument. Tk does have a means of doing that.

-command => [ Car->can('Race'), 'Car' ],

This may or may not be a little faster, but it's definitely not as clear as

-command => sub { Car->Race() },

As for subroutines in other packages? If you have something that's called using

Car::Race();

it would be called using

-command => \&Car::Race,

But that's not what you have here.

* — Except for modules using AUTOLOAD. This is why autoloaders should override can.


This syntax is symple:

$mw->Button(
        -text    => 'Race',
        -command => \&Car::Race,
)->pack;

But if you need to pass any special arguments to that functions or call it as method, you still need an anon sub:

$mw->Button(
        -text    => 'Race',
        -command => sub { Car->Race(@_) },
)->pack;

This one calls Race as method of package Car and pass all arguments to it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号