2006年03月24日 05:51 [Edit]

この記事をクリップ! newsing it! Buzzurlにブックマーク b.hatena.ne.jp/entry perl - Tie::YAML::Syck works - w/ black magic

何とか動くVersionを作ってたけど....

hikarin.jp: MY_memo[2]
Tie::YAMLSyckというものを作ってみた。
しかしmake testに通らず、結局あきらめることに。
YAML ≒ YAML::Syckという関係だろうか?

まあ、まずは完成品を見てみて下さい。

package Tie::YAML::Syck;
use strict;
use warnings;
our $VERSION = sprintf "%d.%02d", q$Revision: 0.3 $ =~ /(\d+)/g;
use base 'Tie::SaveLater';
use Carp;
use YAML::Syck;

__PACKAGE__->make_subclasses;

sub load{ 
    my $class = shift;
    my $filename = shift; 
    return LoadFile($filename);
}

sub save{
    my $self = shift;
    my $filename = $self->filename;
    DumpFile($filename, damn($self));
    return 1;
}

sub damn { # Aaggghhhh!
    my $self = shift; 
    my $pkg  = ref $self;
    if ($pkg =~  /::HASH$/){
        for my $k ( keys %$self ){
            next if ref $self->{$k};
            $self->{$k} .= '';  # force string
        }
        return $self;
    }
    elsif($pkg =~ /::ARRAY$/){
        for my $i (0..@$self-1){ # ugly as hell;
            next if ref $self->[$i];
            $self->[$i] .= '';
        }
        return $self;
    }else{
        return \do{ my $scalar = $$self };
    }
}

1;
__END__

問題は、このdamn()です。なんでこんなもんが必要なんでしょ?

ヒントを出します。

use strict;use warnings;
use YAML::Syck;
use Tie::Hash;
{
    my %h;
    my $rh = \%h;
    %h = (a=>1, b=>'2', c=>3.1415, d=>4);
    bless $rh => 'Tie::StdHash';
    print Dump($rh);
}
{
    my %h;
    my $th = tie %h, 'Tie::StdHash';
    %h = (a=>1, b=>'2', c=>3.1415, d=>4);
    print Dump($th);
}
__END__

なんと出力されたでしょう?なんとこう出力されるのです。

--- !perl/Tie::StdHash 
a: 1
b: 2
c: 3.1415
d: 4
--- !perl/Tie::StdHash 
a: ~
b: 2
c: 3.1415
d: ~

おわかりいただけたでしょうか?

要は、tie()されている場合に限って、文字列化が一度もなされていないhash中のvalueがundefになっちゃうわけです。

よって、上記の方法で強制的に文字列化しているわけです。

YAML-Syck-0.38/Changes
[Changes for 0.28 - 2006-01-16]

* Undef hash values is now emitted as "~" instead of "".
  Reported by: Tatsuhiko Miyagawa

* FETCH magic of tied variables and loop iterators is now respected.
  Reported by: Tatsuhiko Miyagawa

ここがちょいあやしい。

JSON::SyckもおんなじSyck Codeを使っているので、恐らく同じ問題が発生すると思われます。

普通、tied object を serialize することなんかないので、こんな機会でもない限りわかりませんよね。

それで、一応動くようになったversionですが、せっかくのSyckの速度がこれでは台無しです。ということでReleaseは控えておく事にします。Audreyたんには報告入れときますが。今日本に向かっている最中かも。

is( ref( tied (*DANKOGAI) ), 'Subtle::Bugs', 'Signature');


この記事へのトラックバックURL

この記事へのソーシャルブックマーク
はてなブックマーク
Livedoorクリップ
0 Buzzurl