2

タイトルが示すように、Perlで、サブルーチン参照のリストを含むハッシュを保存するにはどうすればよいですか?たとえば、他のライブラリに含まれているサブルーチンへの参照を含む次のハッシュがあります。

my %testMap = (
  helloTest        => \&runHello,
  goodbyeTest      => \&runGoodbye,
);

次の問題でData::Dumperを使用しようとすると:

my($out) = new FileHandle ">$fileName"; 
my $serialized => Data::Dumper->Dump([\%testMap], [$HASH_REFERENCE]); 
print $out $serialized; 
close $out;

次のようなファイルになります。

$testMap = {
             'goodbyeTest' => sub { "DUMMY" },
             'helloTest' => sub { "DUMMY" }
           };

出力を元のリストに表示されているように見せたい場合、これを行う方法はありますか?

Data :: DumperとStorableを使ったいくつかの実験では、これまで何も判明していません。これは、実行中のコードで参照の実際のコードを使用できないことが原因であると思われます。

4

4 に答える 4

5

Storableバージョン2.05以降、coderefをシリアル化できるようになりました。

use strict;
use warnings;
use Storable;
use Data::Dump 'dump';

{
    no warnings;             # Suppress 'used only once' warning
    $Storable::Deparse = 1;  # Needs to be set to true as per docs
    $Storable::Eval    = 1;       # Same as above
}

sub hello_world { print "Hello world!\n" }

my %hash = (
             helloTest => \&hello_world,
             byeTest   => sub { print "Goodbye!\n" },
           );

store \%hash, 'file';            # Could use freeze/thaw for
my $cloned = retrieve( 'file' ); # in-memory serialization

$cloned->{helloTest}();          # Prints 'Hello world!'
于 2012-09-19T20:20:06.760 に答える
2

$Data::Dumper::Deparse真の値に設定します。

これはB::Deparse、オペコードからソースを再構築するために使用されます。これは、常にではありませんが、通常は機能します。

$ perl -MData::Dumper -e 'sub foo { print "Hello world" };' \
>     -e  '$Data::Dumper::Deparse=1; print Dumper \&foo'
$VAR1 = sub {
            print 'Hello world';
        };

Perlソースコードファイルを解析してサブルーチンのテキストを抽出したい場合、それは非常に異なる問題です。しかし、そのためのパッケージもあります:

# quick and dirty sub extractor
use PPI;
use Data::Dumper;
$doc = PPI::Document->new( "your_source_code_file_name" );
foreach $sub ( @{$doc->find( 'PPI::Statement::Sub' )} ) {
  @t = $sub->tokens;
  $name = $t[2];
  $code = "sub " . join q//, @t[3..$#t];
  $teh_codez{$name} = $code;
}    
print Data::Dumper::Dumper \%teh_codez;
于 2012-09-19T20:29:12.933 に答える
2

まず、Data :: Dumperはデバッグツールであり、シリアライザーではありません。後者を行うのはそれほど得意ではありません。少なくとも、必ずPurityオプションを設定してください。これにより、他の方法では機能しない場合でも機能するようになります。ただし、エイリアスを壊すという問題はまだあります。

Storableは重要なデータには使用する必要があり、重要なデータにはJSON::XSまたはYAMLモジュールを使用します。

第二に、あなたが望むことは、オプションを設定することによって試みるDeparseことができます。

use Data::Dumper qw( Dumper );

my $serialised;
{
   local $Data::Dumper::Purity  = 1;
   local $Data::Dumper::Deparse = 1;
   $serialised = Dumper($struct);
}

クロージャでは失敗し、XSは機能し、有効なプラグマをキャプチャしません。

my $struct = { f => do { my $x = 123; sub { $x } } };

を生成します

$VAR1 = {
          'f' => sub {
                     $x;
                 }
        };
于 2012-09-19T20:40:14.503 に答える
1

呼び出されるサブルーチンの名前とともにハッシュを保存し、取得後にそれらをサブルーチン参照に解決することをお勧めします

このコードはアイデアを示しています

use strict;
use warnings;

my %testMap = (
  helloTest   => 'runHello',
  goodbyeTest => 'runGoodbye',
);

$testMap{$_} = \&{$testMap{$_}} for keys %testMap;

$testMap{helloTest}();
$testMap{goodbyeTest}();

sub runHello {
  print "runHello\n";
}

sub runGoodbye {
  print "runGoodbye\n";
}
于 2012-09-20T00:14:40.053 に答える