Perl   发布时间:2022-04-07  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了perl – 如何在longmess中调整对象的渲染?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我们正在慢慢地将我们的大型Perl应用程序重构为面向对象的接口,特别是对于数据模型.令人讨厌的部分是堆栈跟踪变得不那么有用.举一个捏造的例子:之前.
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在模型类上安装Stringification运算符:

use overload ( '""' => \&Stringify );

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

但这并不影响长篇大论.我想要的是这样的

test at example.pm line 23
    foo('MyApp::Model::User[id=42]','Hello World') called at example.pl line 5

也就是说,应该使用对象的Stringify()方法显示foo()的第一个参数.我怎样才能做到这一点?

解决方法

问题出现在 Carp.pm的这一部分:
sub format_arg {
    my $arg = shift;
    if ( ref($arg) ) {
        $arg = defined($overload::VERSION) ? overload::StrVal($arg) : "$arg";
    }
    ...
}

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

不幸的是,没有直截了当的方法.我们所能做的只是修补Carp :: format_arg sub,例如,

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;
  };
}

事实上,这是不优雅的,应该被用于实用主义:

File 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 – 如何在longmess中调整对象的渲染?全部内容,希望文章能够帮你解决perl – 如何在longmess中调整对象的渲染?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。