gpt4 book ai didi

perl - 如何调整长期物体的渲染?

转载 作者:行者123 更新时间:2023-12-04 06:39:35 24 4
gpt4 key购买 nike

我们正在慢慢地将我们的大型 Perl 应用程序重构为面向对象的接口(interface),尤其是数据模型。令人讨厌的部分是堆栈跟踪变得不那么有用了。举一个虚构的例子:之前。

sub send_message {
my ($user_id, $message) = @_;
...
Carp::confess('test');
}

# output:
test at example.pm line 23
foo('42', 'Hello World') called at example.pl line 5

后。
sub send_message {
my ($user, $message) = @_;
...
Carp::confess('test');
}

# output:
test at example.pm line 23
foo('MyApp::Model::User=HASH(0x2c94f68)', 'Hello World') called at example.pl line 5

所以现在我看不到哪个用户被传递给 foo() ,我只看到类名(已经记录在案)和对象的一些内存地址。

我尝试使用overload.pm在模型类上安装字符串化运算符:
use overload ( '""' => \&stringify );

sub stringify {
my ($self) = @_;
return sprintf '%s[id=%d]', ref($self), $self->id;
}

但这并不影响longmess。我想要的是这样的:
test at example.pm line 23
foo('MyApp::Model::User[id=42]', 'Hello World') called at example.pl line 5

foo()的第一个参数应使用对象的 stringify() 显示方法。我怎样才能做到这一点?

最佳答案

问题出在 Carp.pm 的这一部分:

sub format_arg {
my $arg = shift;
if ( ref($arg) ) {
$arg = defined($overload::VERSION) ? overload::StrVal($arg) : "$arg";
}
...
}

也就是说,当参数可能是重载对象时,任何字符串化重载都会被 StrVal helper 规避。 ,这会强制默认字符串化。

不幸的是,没有直接的解决方法。我们所能做的就是猴子补丁 Carp::format_arg子,例如
BEGIN {
use overload ();
use Carp ();
no warnings 'redefine';
my $orig = \&Carp::format_arg;

*Carp::format_arg = sub {
my ($arg) = @_;
if (ref $arg and my $stringify = overload::Method($arg, '""')) {
$_[0] = $stringify->($arg);
}
goto &$orig;
};
}

事实上,这是不优雅的,应该放入一个 pragma 中:

文件 Carp/string_overloading.pm :
package Carp::string_overloading;

use strict; use warnings;

use overload ();
use Carp ();

# remember the original format_arg method
my $orig = \&Carp::format_arg;
# This package is internal to Perl's warning system.
$Carp::CarpInternal{ __PACKAGE__() }++;

{
no warnings 'redefine';
*Carp::format_arg = sub {
my ($arg) = @_;
if ( ref($arg)
and in_effect(1 + Carp::long_error_loc)
and my $stringify = overload::Method($arg, '""')
) {
$_[0] = $stringify->($arg);
}
goto &$orig;
};
}

sub import { $^H{__PACKAGE__ . "/in_effect"} = 1 }

sub unimport { $^H{__PACKAGE__ . "/in_effect"} = 0 }

sub in_effect {
my $level = shift // 1;
return (caller $level)[10]{__PACKAGE__ . "/in_effect"};
}

1;

然后代码
use strict; use warnings;

package Foo {
use Carp ();

use overload '""' => sub {
my $self = shift;
return sprintf '%s[%s]', ref $self, join ", ", @$self;
};

use Carp::string_overloading;
sub foo { Carp::confess "as requested" }

no Carp::string_overloading;
sub bar { Carp::confess "as requested" }
}

my $foo = bless [1..3] => 'Foo';

eval { $foo->foo("foo") };
print $@;
eval { $foo->bar("bar") };
print $@;

输出:
as requested at test.pl line 12.
Foo::foo('Foo[1, 2, 3]', 'foo') called at test.pl line 20
eval {...} called at test.pl line 20
as requested at test.pl line 15.
Foo::bar('Foo=ARRAY(0x85468ec)', 'bar') called at test.pl line 22
eval {...} called at test.pl line 22

关于perl - 如何调整长期物体的渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18398692/

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