『Rubyによるデザイン・パターン』を読み終えて内部DSLが分かった気になった。調子に乗ってPackRat*1をPerlに移植してみた。少しPerl風にアレンジ。
まず、内部DSLから。
# 内部DSL(backup.pr) backup { from => '/home/hoge/old1', to => '/tmp/backup', file_regx => '^.+\.(txt|doc)$', interval => 60, }; backup { from => '/home/hoge/old2', to => '/tmp/backup', file_regx => '^.+\.(mp3|wav)$', interval => 30, };
バックアップの定義を行っている。もちろん文法はPerlに従う。そして、内部DSLを実行する部分は次のとおり。
use strict; use warnings; use threads; use File::Find; # 内部DSLでバックアップ定義するための関数 my @backups; sub backup(&) { push @backups, $_[0]; } # 内部DSLの実行 eval { do "backup.pr"; }; # バックアップのメイン処理 sub backup_main { my %def = $_[0]->(); while (1) { find(sub { if ($_ =~ /$def{file_regx}/) { print "backup $File::Find::name to $def{to}\n"; } else { print "not backup $File::Find::name\n"; } }, $def{from}); sleep($def{interval}); } } # バックアップ実行 my @ths; push @ths, threads->create(\&backup_main, $_) for (@backups); $_->join() for (@ths);
内部DSLで定義したクロージャをbackup関数経由で受け取り実行するだけ。