可以利用哪种现代(5.10之后)技巧来使Data :: Dumper :: Simple类似工作?

dax*_*xim 7 perl metaprogramming

存在几个可以显示变量名称而不需要程序员明确重复名称的转储器.

› perl -MData::Dumper::Simple -e'my $foo = 42; print Dumper($foo)'
$foo = 42;
Run Code Online (Sandbox Code Playgroud)

诡计是源过滤器(经常中断).

› perl -MDDS -e'my $foo = 42; DumpLex $foo'
$foo = 42;
Run Code Online (Sandbox Code Playgroud)

技巧是PadWalker.

它们在某种程度上也适用于其他类型的变量,但切片或其他复杂表达式存在问题.

可以利用哪个现代(5.10之后)eval技巧来制作以下示例转储器(如:数据结构查看器,不可用的代码生成器)?重点是始终打印好的名称,接受多个表达式,而不需要使用额外的参考级别来更改表达式.

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;
Run Code Online (Sandbox Code Playgroud)

tob*_*ink 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};
Run Code Online (Sandbox Code Playgroud)