gpt4 book ai didi

perl - mro、goto 和 set_subname 如何交互?

转载 作者:行者123 更新时间:2023-12-02 09:44:55 25 4
gpt4 key购买 nike

这是一个关于 mro.pm 以及与 set_subnamegoto 相互作用的复杂问题

在解决问题时,我认为我的误解的核心与 mro.pm 的工作方式有关 - 特别是关于 set_subname

这三种结构有什么区别,

  1. 简单调用set_subname

    *Foo::bar = set_subname( 'Foo::bar', $codeRef );
  2. 包装set_subname的匿名子

    *Foo::bar = sub {
    my $codeRef2 = set_subname('Foo::bar', $codeRef);
    goto $codeRef2
    };
  3. 使用 set_subname 设置名称的匿名子

    *Foo::bar = set_subname(
    'Foo::bar',
    sub { goto $codeRef }
    );

具体来说,Mojo 测试套件在将匿名子应用到 Mojo::Utils's monkey_patch 时会因这些修改而失败。针对 t/mojo/websocket_proxy.t 运行上述两个变体,

  • 使用 2(第二个)选项我有

    *{"${class}::$k"} = sub {                                                                                                                          
    my $cr = set_subname("${class}::$k", $patch{$k});
    goto $cr;
    };

    我明白了

    Mojo::Reactor::Poll: Timer failed: Can't locate object method "send" via package "Mojo::Transaction::HTTP" at t/mojo/websocket_proxy.t line 66.
  • 有了 3(第三个)选项,

    *{"${class}::$k"} = set_subname("${class}::$k", sub { goto $patch{$k} })

    我明白了

    No next::method 'new' found for Mojolicious::Routes at /usr/lib/x86_64-linux-gnu/perl/5.28/mro.pm line 30.

显然,第一个版本可以工作(来 self 链接的代码),问题是为什么其他两个变体给我带来不同的错误(尤其是第二个变体)以及那里发生了什么 - 为什么它们不工作?

最佳答案

您的第二个选项不起作用,因为您用作包装器的子组件与内部子组件的原型(prototype)不匹配。 monkey_patch 不仅用于方法,而且这改变了一些函数的解析方式。特别是,Mojo::Util::steady_time 具有空原型(prototype),并且通常在不使用括号的情况下调用。

*{"${class}::$k"} = Sub::Util::set_prototype(
Sub::Util::prototype( $patch{$k} ),
Sub::Util::set_subname(
"${class}::$k",
sub {
my $cr = Sub::Util::set_subname("${class}::$k", $patch{$k});
goto $cr;
}
)
);

第三个构造不起作用,因为您正在使用 goto 从调用堆栈中删除重命名的包装器子程序,只留下没有名称的内部子程序。这会破坏 next::method 查找正确方法名称的能力。

关于perl - mro、goto 和 set_subname 如何交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58677042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com