ちょっとしたコードを検証するコツ

とりあえずPerl限定のお話で。

まぁ皆同じようなことは多分してると思うのでぐだぐだと何か言うことも無いんだけど、自分流のやり方を覚書程度にメモするという意味でここに残しておきます。

まず以下のようなfoo.plを用意します。

#!/usr/local/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
use YAML();
sub p (@) { local $Data::Dumper::Indent = 1; print Dumper(@_) }
sub P (@) { print YAML::Dump(@_)   }
use Perl6::Say;
use Path::Class;



__END__

自分の環境にあわせてお好みのuse文を入れておきましょう。Perl 5.10とかならPerl6::Sayはいらないですね。

ちなみにp関数やP関数は、いちいち「print Dumper $c」とか打つのが面倒なのでショートカット用に用意してます。こういった自分だけのショートカット関数も入れておきましょう。

で次に検証したいコードを書きます。

my $data = q{
hoge=foiejfiejf
aurl=http://example.com/foo/?guid=ON
burl=http://example.com/foo/?guid=ON
muge=fjidjfo
};

$data =~ s{^([ab]url=http://)example.com}{$1.'a'}egm;
print $data;

__END__

で似たような別のコードを検証する場合はコピペで下に押しやって元のコードを残しておきましょう。

__END__を入れればそれ以下のコードをコンパイラに無視させることができるのでPODや#でコメントアウトするよりも簡単楽チンです。

my $data = q{
hoge=foiejfiejf
aurl=http://example.com/foo/?guid=ON
burl=http://example.com/foo/?guid=ON
};

$data =~ s{^(.*=http://)example.com}{'['.$1.']'}egm;
print $data;

__END__

my $data = q{
hoge=foiejfiejf
aurl=http://example.com/foo/?guid=ON
burl=http://example.com/foo/?guid=ON
muge=fjidjfo
};

$data =~ s{^([ab]url=http://)example.com}{$1.'a'}egm;
print $data;

__END__

コードを残しておけば前のコードからの検証をやり直せるので便利です。

コードは基本的に消さずにコピペ&__END__を使って残し続けましょう。

そうして溜まりに溜まった取るに足らないコードは、今や約2万行に達しました。

後で見てみると色々面白かったりします。

例えば僕のfoo.plの14199行目のコード

package Hoge;
 use strict;
 
 sub hoge_alias { print "Hoge::hoge_alias\n" }
 sub hoge       { print "Hoge::hoge\n"       }
 
 package Muge;
 use strict;
 use base qw/Hoge/;
 use Class::C3;
 
 sub hoge {
     my $self = shift;
     #$self->next::method;
     my $level = 0;
    my ($method_caller, $label, @label);
    my %hoge;
    while (@hoge{qw/pack file line subname hasargs wantarray evaltext is_require/} = caller($level++)) {
      @label = (split '::', $hoge{subname});
      $label = pop @label;
      print Data::Dumper::Dumper \%hoge;
#      last unless
 #       $label eq '(eval)' ||
  #      $label eq '__ANON__';
    }

 }
 
no strict 'refs';
 sub hoge_alias; *{"Muge::hoge_alias"} = \&hoge;
 #sub hoge_alias { eval { &hoge  } }
 Muge->hoge_alias; # Hoge::hoge と表示される

何がやりたかったのだろうw

多分このコードはClass::C3を使ってるようなメソッドのエイリアスをどうにかして実現できないか頑張ってたときのコードかな?

13777行目のコード

package UNIVERSAL;
sub cant {
    my ($pkg, @args) = @_;
    if ( my $sub = $pkg->can( @args ) ) {
        return bless $sub ,'UNIVERSAL::cant::false';
    }
    return 1;
}
package UNIVERSAL::cant::false;
use overload (
    q{""}   => sub { return shift },
    q{bool} => sub { return },
);

package main;
sub hoge { print 'hoge';}

if ( my $sub = main->cant('hoge') ) {
    print '存在しない';
}
else {
    print '存在する';
    print $sub;
    $sub->();
}

UNIVERSALで遊んでるよw

多分この記事書くために色々いじって遊んでたときのコードですね。



という感じでちょこっと検証したいだけのどうでもいいコードはこういう風にすれば面倒臭くないし楽でかつ便利に扱えますよ、と。

ただコードの断片にもそれなりに意味を持たせたいのであれば

コードポケット - アプリケーションをささっと作るコツ - (ひ)メモ

この記事のように分類分けして溜め込んでいくやり方のほうが良いと思います。

でも僕は面倒臭がりなのでコードの断片に名前付ける僅かな思考の中断すら煩わしく思ってしまうので中々こういった仕組みまで導入できてないんですよね。やりたいなーとは思いつつも重い腰が上がらない的な。

纏まらないまま終わり。