Perl 可以利用哪种现代(5.10版后)技巧使Data::Dumper::Simple工作起来类似?
有几个转储程序可以显示变量的名称,而无需程序员明确地重复该名称Perl 可以利用哪种现代(5.10版后)技巧使Data::Dumper::Simple工作起来类似?,perl,metaprogramming,Perl,Metaprogramming,有几个转储程序可以显示变量的名称,而无需程序员明确地重复该名称 › perl -MData::Dumper::Simple -e'my $foo = 42; print Dumper($foo)' $foo = 42; 诡计是源过滤器(经常中断) 诡计是 它们在某种程度上也适用于其他类型的变量,但切片或其他复杂表达式是有问题的 以下示例转储程序(如:data structure viewer,而不是eval-able code producer)可以使用哪种现代(5.10后)技巧工作?重点是始
› perl -MData::Dumper::Simple -e'my $foo = 42; print Dumper($foo)'
$foo = 42;
诡计是源过滤器(经常中断)
诡计是
它们在某种程度上也适用于其他类型的变量,但切片或其他复杂表达式是有问题的
以下示例转储程序(如:data structure viewer,而不是eval
-able code producer)可以使用哪种现代(5.10后)技巧工作?重点是始终打印好的名称,接受多个表达式,并且不需要使用额外的引用级别更改表达式
use 5.020; use Syntax::Construct qw(%slice);
use strictures;
use Acme::Hypothetical::Dumper 'd';
my %foo = (
Me => 'person',
You => 'beloved one',
Them => 'space aliens',
);
d %foo, $foo{'Me'}, @foo{qw(You Me)}, %foo{qw(You Me)};
# %foo = ('Me' => 'person', 'Them' => 'space aliens', 'You' => 'beloved one');
# $foo{'Me'} = 'person';
# @foo{qw(You Me)} = ('beloved one', 'person');
# %foo{qw(You Me)} = ('Me' => 'person', 'You' => 'beloved one');
my @bar = qw(Me You Them);
d @bar, $bar[0], @bar[2, 1], %bar[2, 1];
# @bar = ('Me', 'You', 'Them');
# $bar[0] = 'Me';
# @bar[2, 1] = ('Them', 'You');
# %bar[2, 1] = (2 => 'Them', 1 => 'You');
use LWP::UserAgent qw();
my $ua = LWP::UserAgent->new;
d $ua->{ssl_opts}{verify_hostname};
# $ua->{ssl_opts}{verify_hostname} = 1;
输出中的空白与您的示例不完全匹配,但这非常接近
use v5.14;
use strict;
use warnings;
BEGIN {
package Acme::Hypothetical::Dumper;
use Keyword::Simple;
use PPR;
use Data::Dumper;
use B 'perlstring';
sub import {
my ( $class, $fname ) = ( shift, @_ );
$fname ||= 'd';
Keyword::Simple::define $fname => sub {
my $code = shift;
my ( @ws, @vars, @ws2 );
while ( $$code =~ / ^ ((?&PerlOWS)) ((?&PerlTerm)) ((?&PerlOWS)) $PPR::GRAMMAR /x ) {
my $len = length( $1 . $2 . $3 );
push @ws, $1;
push @vars, $2;
push @ws2, $3;
substr( $$code, 0, $len ) = '';
$$code =~ s/ ^ (?&PerlComma) $PPR::GRAMMAR //x;
}
my $newcode = perlstring( $class ) . '->d(';
while ( @vars ) {
my $var = shift @vars;
$newcode .= sprintf(
'%s%s,[%s],%s',
shift( @ws ),
perlstring( $var ),
$var,
shift( @ws2 ),
);
}
$newcode .= ');';
substr( $$code, 0, 0 ) = $newcode;
return;
};
}
our $OUTPUT = \*STDERR;
sub d {
my ( $class, @args ) = ( shift, @_ );
while ( @args ) {
my ( $label, $value ) = splice( @args, 0, 2 );
my $method = 'dump_list';
if ( $label =~ /^\$/ ) {
$method = 'dump_scalar';
$value = $value->[0];
}
elsif ( $label =~ /^\%/ ) {
$method = 'dump_hash';
}
printf { $OUTPUT } "%s = %s;\n", $label, $class->$method( $value );
}
}
sub dump_scalar {
my ( $class, $value ) = ( shift, @_ );
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
return Dumper( $value );
}
sub dump_list {
my ( $class, $value ) = ( shift, @_ );
my $dumped = $class->dump_scalar( $value );
$dumped =~ s/\[/(/;
$dumped =~ s/\]/)/;
return $dumped;
}
sub dump_hash {
my ( $class, $value ) = ( shift, @_ );
my $dumped = $class->dump_scalar( { @$value } );
$dumped =~ s/\{/(/;
$dumped =~ s/\}/)/;
return $dumped;
}
$INC{'Acme/Hypothetical/Dumper.pm'} = __FILE__;
};
use Acme::Hypothetical::Dumper 'd';
my %foo = (
Me => 'person',
You => 'beloved one',
Them => 'space aliens',
);
d %foo, $foo{'Me'}, @foo{qw(You Me)}, %foo{qw(You Me)};
my @bar = qw(Me You Them);
d @bar, $bar[0], @bar[2, 1], %bar[2, 1];
use LWP::UserAgent qw();
my $ua = LWP::UserAgent->new;
d $ua->{ssl_opts}{verify_hostname};
我觉得这是个XY问题。你到底想完成什么?不如阅读你自己的源代码,就像一个有趣的应用程序的错误屏幕一样。那不是Data::Printer吗?@briandfoy nope,Data::Printer不知道变量名。是的,这个功能很好。两年前,我用
PPI
为Data::Printer
做了类似的事情。Damian最近在他的PPR
模块中提出了一种更高效的Perl解析器,请参阅。另请参见一些其他链接。PS:如果您想知道为什么我要将空白保存到@ws
和@ws2
中,然后小心地将其插入生成的代码中,那是因为空白可能包含换行符,并且我试图避免在错误消息中打断行号。
use v5.14;
use strict;
use warnings;
BEGIN {
package Acme::Hypothetical::Dumper;
use Keyword::Simple;
use PPR;
use Data::Dumper;
use B 'perlstring';
sub import {
my ( $class, $fname ) = ( shift, @_ );
$fname ||= 'd';
Keyword::Simple::define $fname => sub {
my $code = shift;
my ( @ws, @vars, @ws2 );
while ( $$code =~ / ^ ((?&PerlOWS)) ((?&PerlTerm)) ((?&PerlOWS)) $PPR::GRAMMAR /x ) {
my $len = length( $1 . $2 . $3 );
push @ws, $1;
push @vars, $2;
push @ws2, $3;
substr( $$code, 0, $len ) = '';
$$code =~ s/ ^ (?&PerlComma) $PPR::GRAMMAR //x;
}
my $newcode = perlstring( $class ) . '->d(';
while ( @vars ) {
my $var = shift @vars;
$newcode .= sprintf(
'%s%s,[%s],%s',
shift( @ws ),
perlstring( $var ),
$var,
shift( @ws2 ),
);
}
$newcode .= ');';
substr( $$code, 0, 0 ) = $newcode;
return;
};
}
our $OUTPUT = \*STDERR;
sub d {
my ( $class, @args ) = ( shift, @_ );
while ( @args ) {
my ( $label, $value ) = splice( @args, 0, 2 );
my $method = 'dump_list';
if ( $label =~ /^\$/ ) {
$method = 'dump_scalar';
$value = $value->[0];
}
elsif ( $label =~ /^\%/ ) {
$method = 'dump_hash';
}
printf { $OUTPUT } "%s = %s;\n", $label, $class->$method( $value );
}
}
sub dump_scalar {
my ( $class, $value ) = ( shift, @_ );
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
return Dumper( $value );
}
sub dump_list {
my ( $class, $value ) = ( shift, @_ );
my $dumped = $class->dump_scalar( $value );
$dumped =~ s/\[/(/;
$dumped =~ s/\]/)/;
return $dumped;
}
sub dump_hash {
my ( $class, $value ) = ( shift, @_ );
my $dumped = $class->dump_scalar( { @$value } );
$dumped =~ s/\{/(/;
$dumped =~ s/\}/)/;
return $dumped;
}
$INC{'Acme/Hypothetical/Dumper.pm'} = __FILE__;
};
use Acme::Hypothetical::Dumper 'd';
my %foo = (
Me => 'person',
You => 'beloved one',
Them => 'space aliens',
);
d %foo, $foo{'Me'}, @foo{qw(You Me)}, %foo{qw(You Me)};
my @bar = qw(Me You Them);
d @bar, $bar[0], @bar[2, 1], %bar[2, 1];
use LWP::UserAgent qw();
my $ua = LWP::UserAgent->new;
d $ua->{ssl_opts}{verify_hostname};