Hatena::Groupperl

local $PERL_MEMO;

November 07, 2013

[][]minil release時にターゲット以外のバージョンを書き換えられないようにする方法

minil.tomlを修正しようという話です。

問題

上のリポジトリのbenchフォルダみたいに、以前のバージョンと性能比較するために古いバージョンのモジュールをリポジトリに含めてるみたいな場合があります。古いモジュールには$VERSIONが振ってあって、当然これは未来永劫変更するつもりのないものです。

ところで、MinillaのCLIであるminilにはminil releaseコマンドがあります。これは

  • Change のリリース時間の自動挿入
  • 修正のコミットとバージョンタグ付け
  • git push origin master

を勝手にやってくれる大変ありがたいコマンドなのですが、ソースファイル内のバージョンの書き換えを .pm ファイルや .t ファイルを探して勝手にやってくれるという機能もあって、それが今回のケースでは余計なお世話をしてくれます。つまり、古いバージョンのpmファイルも勝手に書き換えちゃうんですね。

対策

問題はリリース対象であるlibフォルダ以外のpmファイルを探しちゃうところにあります。Minillaは「設定より規約」ということで、gitリポジトリの内容が、

lib/以下にPure Perl でモジュールが書かれている

実行ファイルはなんであれ、script/ディレクトリ以下にある

モジュールは Git でメンテナンスされており、git ls-files は、リリースするものにマッチする

モジュールは、cpanfileに予め必要なものの静的なリストがある

モジュールには、Changes がある

Minilla - CPAN モジュールオーサリングツール - perldoc.jp

上記のようなルールに基づいて構成されていることを期待しています。今回のような規約外のことをやろうとするときはminil.tomlという設定ファイルをプロジェクトのルートフォルダに作ってやると良いらしいです。

name = "Uc-Model-Twitter"

[FileGatherer]
exclude_match = ['^bench/.*']

FileGatherer.exclude_match にMinillaのperlファイル収集から除外したいファイルの正規表現を書くと、Minilla::Filegathererに設定がわたっていい感じにしてくれます。

おまけのminil.tomlの話

name はプロジェクトの名前とモジュール名が一致しない時に使います。今回の場合だと p5-uc-model-twitterというフォルダ名でUc::Model::Twitterを開発してます。

思い出したので書いておきますが、TOMLファイルは設定の名前と設定値の間の = の両端に空白がないとシンタックスエラーになります。MinillaのPODに空白のないサンプルがあってちょっとハマった。

[][]Encode::Entity::NCR v0.0.2 release

3年半ぶりの更新。といっても機能的な追加はなく別のモジュールの更新のついでにドキュメントの修正とMinillizeしました。

$ cpanm https://github.com/UCormorant/p5-encode-entity-ncr/archive/0.0.2.tar.gz 

でインストールできます。cpanm についてはググしてください。

see also

July 12, 2013

[][]DATAを開くとデバッグがだるい

use autobox::dump;
use YAML;
print Load(do { local $/; <DATA>; })->perl;
sleep 100;
exit;
__DATA__
---
foo: hoge
bar: fuga
baz: piyo

みたいな処理を書くとsleepしてる間ソースファイルがreadonlyになって不便。

追記

開き直さないんだったら閉じたらいい。

print Load(do { local $/; $a = <DATA>; close DATA; $a; })->perl;

May 05, 2010

[][]YouTube Downloader アップデート

id:ishiducaさんの記事WWW::YouTube::Downloadがいいらしいと知ったので、以前作ったYouTube Downloaderをこのモジュール使って作りなおしてみました。

ダウンロード

Download Sourcってところか、yt.pl ってファイルをクリックしてクリップボードにコピーしたり raw ファイル落としたりしてください。

使い方

yt.pl <video_id> か、 yt.pl <url>で。プレイリストのURL指定すると一括で落とせます。

日記

1年ぶりのアップデート。たぶん動かなかった。

今回のアップデートできちんと動作するようになったけど、そのかわりフォーマットが指定できないとか保存フォルダの指定不可(カレントディレクトリのみ)とか断片化防止のアイデアが使えないとか、機能は減りました。ねむい。

MarMar2012/08/20 09:40That hits the tgaert dead center! Great answer!

lynpgonklynpgonk2012/08/22 15:16xxTSyn <a href="http://fzbpdhiuqbuv.com/">fzbpdhiuqbuv</a>

March 12, 2010

[][][]Win環境でモジュールの配布パッケージを作ってみる(草稿)

日を置くと情熱も記憶も失われるもので、もう何書こうとしてたか思い出せません。ですので、自分の環境で配布パッケージ作る時に引っかかった所を断片的に記録しておきます。

環境

モジュール作成からパッケージまでの10の手順

  1. このへん読む
  2. Module::Starter/Module::Starter::PBPインストール
  3. $ perl -MModule::Starter::PBP=setup
  4. 出来たテンプレートフォルダ(%HOME%/.module_starter/PBP)をC:\Perl\PBPに移動
  5. configのテンプレートページのとこC:\Perl\PBPに書き換え
  6. $ module-starter --module=Hoge
  7. Hoge/lib/Hoge.pm 書く
  8. $ PATH C:\Perl\bin;C:\Program Files\Microsoft Visual Studio 9.0\VC\bin
  9. $ perl Makefile.pl
  10. $ make dist

ツマルの詰まったとこ

  • Win 2000/XP特有?の問題として、%HOME%がだいたいDocuments and Settings/fugaとか、パスに空白が入ってるせいでmodule-starterがテンプレートページのパスが分からないとかのエラー吐く
    • スペースはいってないパスにPBPディレクトリを移動して解決
  • CygwinのせいなのかMakefileしてつくったmakeが"multiple target patterns. Stop"とかでエラー
    • コマンドPATHで一時的にperlvc(とあと%System%とか/binとかあったかもしれない)の最小構成にする。そのあいだにperl Makefile.pl etc
    • PATHはコマンドプロンプトが開いてる間、渡されたパスを覚えてるだけなので「環境変数書き変わるかも…」とか心配しなくていい。別のプロンプト起動すればいつもどおりである

おしまい

こんな感じで案外あっさり出来てしまいました。それでもそれなりに環境整えてやらないと出来るものもできないんだなぁというのが今回の感想です。あ、これ草稿のまま終わりそう。夜。

cf.

AddyAddy2011/06/05 09:30Hey, that post leaves me feeilng foolish. Kudos to you!

pzhmlhalpzhmlhal2011/06/05 17:55TpHTVq <a href="http://fjlidowwjrli.com/">fjlidowwjrli</a>

vmenumsdhqvmenumsdhq2011/06/06 22:29YduFNj , [url=http://atmticemgxor.com/]atmticemgxor[/url], [link=http://lgdhqdabbown.com/]lgdhqdabbown[/link], http://pfnsyxtchlrl.com/

ohljogoohljogo2011/06/07 17:55NtmO91 <a href="http://eubvdbyyziyx.com/">eubvdbyyziyx</a>

gldecnzogldecnzo2011/06/09 19:286zOWRa , [url=http://vajhjtqiwcpz.com/]vajhjtqiwcpz[/url], [link=http://adsgrcuxunqi.com/]adsgrcuxunqi[/link], http://cjtppvomotap.com/

IrisIris2013/02/04 18:28An ansewr from an expert! Thanks for contributing.

lzilwttcmlzilwttcm2013/02/06 14:494EMtR6 , [url=http://ioyjuyewplqv.com/]ioyjuyewplqv[/url], [link=http://gxzncnccoffm.com/]gxzncnccoffm[/link], http://wivzedayeeft.com/

pdptkeuawgwpdptkeuawgw2013/02/06 22:53dVk4bZ <a href="http://confqsyoolmp.com/">confqsyoolmp</a>

March 07, 2010

[][]\(hoge) -> ?

print \(a..z);
# SCALAR(0x182fe2c)SCALAR(0x182fe38)...SCALAR(0x182ff4c)SCALAR(0x182ff58)

なにこのミラクル構文。リスト(配列じゃなくてリスト構文)のリファレンス取ろうとすると中身のリファレンスのリスト返すのか。すげー

追記

@a = 0..9; @b = A..Z; @c = a..z;

print \(@a);
# SCALAR(0x182fd8c)SCALAR(0x182fd98)...SCALAR(0x182fec4)SCALAR(0x182fed0)

print \(@a,@b,@c);
# ARRAY(0x182f984)ARRAY(0x182fb04)ARRAY(0x182fde0)

リストの中身が複数に分かれると、それぞれのリファレンスを返すみたい。

ちなみに、複数の配列のすべての中身のリファレンスが欲しい時は

print \(@_=(@a,@b,@c));
# SCALAR(0x2861ac)SCALAR(0x286284)...(many)...SCALAR(0x1830368)SCALAR(0x1830374)

のように、一つの配列に代入してやるといいみたい。いいシュガー発見した気がする。

追記2

print \(@{[@a,@b,@c]});

こっちのほうがスマートですね。

[][][]配列をshuffle(ランダムに並べ替えたい)/take potluck(ランダムに抜き出したい) - 爆速編

前回の更新ではベンチ取らないでやってたので今回は高速化に挑戦。

まずはベンチマーク

使ったコードはこちら。

#!perl
use Benchmark qw(timethese cmpthese);
use List::Util;
my @a = &#39;Aa&#39;..&#39;Zz&#39;; # 0 .. 675

cmpthese(timethese(10000, {
  &#39;L::U::shuffle&#39; => sub { List::Util::shuffle(@a) },
  shuffle_simple  => sub { shuffle_simple(@a) },
  shuffle         => sub { shuffle(@a) },
  L_U_shuffle     => sub { L_U_shuffle(@a) },
}));


sub shuffle_simple { return sort { int(rand 3) -1 } @_ }

sub shuffle {
  my @old = @_; local $_;
  my ($i, $new) = ($#old+1, 0);
  map {
    $_ = $old[$new = rand $i--];
    $old[$new] = $old[$i];
    $_;
  } 0 .. $#old
}

sub L_U_shuffle {
  my @old = \(@_);
  my $n; my $i = @_;
  map {
    (${$old[$n = rand $i--]}, $old[$n] = $old[$i])[0];
  } @_
}

L_U_shuffleはList::Util::shuffleのpure perl版です。

で、結果が以下。

                   Rate shuffle L_U_shuffle L::U::shuffle shuffle_simple
shuffle           215/s      --        -73%          -97%          -100%
L_U_shuffle       794/s    270%          --          -90%           -99%
L::U::shuffle    7622/s   3453%        859%            --           -94%
shuffle_simple 125000/s  58171%      15635%         1540%             --

…(shuffle_simpleはともかく)勝負にならんな!あとXSのshuffle速すぎ。

なんでこんなに差がつくかというと、L_U_shuffleは実体をコピーするのではなくさっきの記事の方法を使ってリファレンスのリストを作ってそいつを回しているのが原因だと思う。余計な代入も一切発生しない。あと僕の作ったshuffleはmap回すのに0..$#oldみたいないらん配列作ってるしさらに遅い。で、3倍近く差がつく。この点を改良して最速shuffle/take potluckを作ります。

並べ替え

sub shuffle_fast(@) {
  my @old = \(@_);
  my $n; my $i = @_;
  map {
    (${$old[$n = rand $i--]}, $old[$n] = $old[$i])[0];
  } @_;
}

ええパクリです。でも僕の環境だとpure perlのList::Util::shuffleの倍は出ます。何故か。mapの中を1行にしただけなのに。

参考ベンチ(試行回数1000)
              Rate      shuffle  L_U_shuffle shuffle_fast
shuffle      216/s           --         -46%         -72%
L_U_shuffle  396/s          84%           --         -49%
shuffle_fast 774/s         259%          95%           --

適当に抜き出す

sub potluck_fast($;$) {
  my $i = my @a = \(@{+shift});
  my $n = shift || int rand $i;
     $n = $i if $n > $i;
  map {
    (${$a[$n = rand $i--]}, $a[$n] = $a[$i])[0];
  } 0 .. $n-1;
}
warn potluck_fast([0..9,A..Z,a..z],20);
# XK7kgQq6Dn1RLVa8ozOW

ぱくぱく。使い方は前回同様、第1引数に配列のリファレンスを、第2引数に抜き出したい数を渡します。

参考ベンチ(試行回数1000)
              Rate      potluck potluck_fast
potluck      248/s           --         -73%
potluck_fast 925/s         273%           --

おしまい

爆速って程でもなかったかな。しかし既存のshuffleよりはずっと速くなったはず。そのへんのよりは3倍速い。

List::Util使えるんだったらshuffleはList::Util使いましょう。爆速です。potluckみたいなことしたいときも

(List::Util::shuffle('Aa'..'Zz'))[0..rand(676)]

とかすれば爆速間違いなし。XSにはどう頑張っても勝てんわ。

cf.

MarcusMarcus2013/02/02 03:24Wonderful explanation of facts avaliable here.

aljpnasaljpnas2013/02/02 19:315v9ahV <a href="http://cpisumrqicws.com/">cpisumrqicws</a>

einmvsyipeinmvsyip2013/02/04 12:44KzH6ZP <a href="http://rkhlctayydot.com/">rkhlctayydot</a>