perl - 我可以在包中注入(inject) perl sub 吗?

标签 perl mojolicious

我希望能够在类中动态“注入(inject)”方法,类似于 Mojolicious 助手发生的情况。像这样的事情:

my $s = SomeThing->new;

$s->helper(do_this => sub {
               my $self = shift;
               $foo = shift;
           });

$s->do_this('bar');

我已经做了一些距离,但我希望注入(inject)的子程序在它们注入(inject)的类的命名空间中运行,而不是在 main 中运行。换句话说,目前的工作原理如下:

$s->do_this('bar');

print 'in main:      ', $foo;             

这会打印“bar” - 我不希望它如此,而我想要这个

print 'in SomeThing: ', $SomeThing::foo;

改为打印“bar”

虽然这有效,但对我来说似乎很笨拙

$s->helper(do_this => sub {
               my $self = shift;
               ${(ref $self) . '::foo'} = shift;
           });

$s->do_this('foo');

print 'in SomeThing: ', $SomeThing::foo;  # now this prints "foo"

发生这一切的包看起来像这样:

package SomeThing {
    use Mojo::Base -base;
    use Carp;

    sub helper {
        my $self = shift;
        my $name = shift || croak "The helper name is required";
        my $sub = shift || sub {};

        my $namespace = __PACKAGE__;
        no strict 'refs';
        { 
            *{"$namespace\::$name"} = $sub
        }
    }
};

有办法做到这一点吗?我怀疑我会把严格性搞得一团糟——但我还不想放弃(这将是一个值得学习的好技巧)。

最佳答案

您要求更改与已编译的匿名子程序关联的包,以便进行变量查找。不知道可不可以。

即使有可能,这也不是您想要做的事情,因为您的代码仍然无法工作。您必须将 use vars qw( foo ); 添加到找到 sub { } 文字的文件中。如果您在 Something.pm 中访问了它,那么除了使用 our $foo;use vars qw( $foo ); 之外。

这非常神奇且困惑。通过使用访问器可以轻松避免这种情况。简单替换

$s->helper(
   do_this => sub {
      my $self = shift;
      $foo = shift;
   },
);

$s->helper(
   do_this => sub {
      my $self = shift;
      $self->foo(shift);
   },
);

如果您还需要添加访问器,可以使用以下内容:

$s->helper(
   foo => sub {
      shift;
      state $foo;
      $foo = shift if @_;
      $foo
   },
   do_this => sub {
      my $self = shift;
      $self->foo(shift);
   },
);

顺便说一句,来自 Mojo::Utilmonkey_patch可以用作 helper 的替代品。 (感谢 @brian d foy 的提出。)它做同样的事情,但它有两个额外的好处:

  1. 您不需要支持它。
  2. 它设置 anon sub 的名称,以便堆栈跟踪使用有意义的名称而不是 __ANON__

切换到 monkey_patch 并不能解决您的问题,但除了我上面提到的方法的改变之外,我确实建议使用它(或类似的)。

use Mojo::Util qw(  );
sub helper { shift; Mojo::Util::monkey_patch(__PACKAGE__, @_); }

关于perl - 我可以在包中注入(inject) perl sub 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59627050/

相关文章:

perl - 我怎样才能让 Devel::Cover 结果显示在 Hudson 中?

perl - 不确定我是否正确使用了 Perl 的 Try::Tiny

bash - 将 SSH 流作为 Perl 脚本输入而不是物理文件

perl - 如何使用 Expect.pm 将箭头键按下发送到进程

html - Mojolicious 响应的基本 URL

linux - 关闭到 sendmail 的管道时出错

perl - 如何在 Mojolicious 中动态添加和删除路由?

perl - mojolicious中路线名称的目的是什么?

Perl Mojolicious - 如何让它一次处理多个连接?

linux - 如何获取管道另一侧的pid?