2009/06/04 (木)
■ MacNicoTunes

http://brpg.hp.infoseek.co.jp/macnicotunes/
これはすばらしいスタンドアロンプレイヤー。
で、他のアプリからスクリプトで MacNicoTunes で動画開きたいんですが、AppleScript でイベント送るのはどうにもうまくいかなくて、とりあえず
on run argv
tell application "System Events"
set the clipboard to item 1 of argv
tell process "MacNicoTunes"
set frontmost to true
click menu item "Open Video.." of menu "File" of menu bar 1
keystroke "v" using {command down}
keystroke return
end tell
end tell
end run
みたいに無理矢理やってうごいてるんですが、AppleScript の口なり open -a MacNicoTunes で開けるようにするのは難しいでしょうかねー。Dock にリンクをドロップして開く機能はあるので、口はありそうなんですが、ソースをみた感じでは AppleScript から直接イベントを送るのは難しそうでした。
2009/04/08 (水)
■ DBD::SQLite 1.22_01 と Unicode

Journal of miyagawa (1653) に書いた通りだけど、DBD::SQLite で $dbh->{unicode} オプションをつけたとき、UTF-8 フラグがついていない文字列を渡したときの挙動を変更しました。CPAN に 1.22_01 dev release としてアップロードされてます。
具体的には、いままでは、その文字列の内部エンコーディング(UTF-8 フラグがついてるかどうかにかかわらず)をそのまま保存していて latin-1 の文字列など UTF-8 的に正しくないシーケンスがきたときに DB に壊れた値が入るという問題があったのを、utf8::upgrade を内部的に呼んで、確実に UTF-8 エンコーディングになるようにしました。
もっと日本人のPerlプログラマ的にわかりやすく言うと、UTF-8 な文字列を渡すときはdecode した状態でわたせ、さもなくば二重エンコードになって文字化けするよ、ということです。
これは DBD::SQLite の POD にもずっと書いてあった(unicode オプションのときは文字列は UTF8 フラグつきでやりとりするよ)のだけど、フラグなしで渡したときの動作がドキュメントと食い違っていて latin-1 文字列でバグが起きていました。
これで DBD::mysql の mysql_enable_utf8 とも動作は同じになりますが、以前の(正しくない)動作に依存しているアプリケーションは動かなくなるかもしれません。
具体的に言うと、ちょっと前の Remedie では JSON 文字列をカラムに保存するのに JSON::XS->new->utf8->encode を利用していたので、このパッチがあたった DBD::SQLite では二重エンコードで文字化けしてしまいました。->utf8 オプションを外すか、現在の Remedie のように ->ascii としてそもそも変換を回避するように変更すれば、現状版でもパッチがあたっていてもどちらでも動きます。
というわけで、http://search.cpan.org/~adamk/DBD-SQLite-1.22_01/ にあがっているのでテストよろしく。
2009/03/13 (金)
■ BEGIN を使わずにコンパイル時にコードを実行する

use Module VERSION の形をつかって VERSION に式をぶちこむ。
use less sub { ("Dyna"."Loader")->can("dl_find_symbol")->(...) }->();
less.pm はとくに import で何もしていないので sub {} で何を返してもおkだけど、そうじゃないモジュールを利用する場合は return () とかする必要がある、かも。
See also: perl から任意の C ライブラリを呼び出す方法 - kazuhoのメモ置き場
2009/02/08 (日)
■ メタプログラミングとevalのベンチマーク

404 Blog Not Found:perl,javascript and more - evalは最後の武器
「evalは最後の武器」というのは、Perlに限らずメタプログラミング可能な言語における鉄則とも言える。たいていの場合、無名関数を生成するだけで同様の目的をより安全かつ高速に行えるのだ。
記事全体には同意するけど、「高速」という部分はどうだろ。Mooseは無名クラスの生成に無名関数ではなくて string eval を使ってクラスをコンパイルしてるんだけど、string eval のほうが実行時に速い、というのがひとつの理由だったとおもう。
こんな単純な例でも、30倍の速度差が出ている。
このコードは benchmark のループ内で毎回 eval を実行しているから、そもそも比較の対象としておかしい。
#!/usr/bin/perl use strict; use warnings; use Benchmark qw/timethese cmpthese/; eval 'package FooEval; sub bar { $_[0] + $_[1] }'; *FooAnon::bar = sub { $_[0] + $_[1] }; cmpthese( timethese( 0, { eval => sub { FooEval::bar( 1, 1 ) == 2 or die; }, anon => sub { FooAnon::bar( 1, 1 ) == 2 or die; } } ) );
実際のメタプログラミングの手法を考えると、まずこういう風に subref を eval をつかったほうほうとそうでない純粋な無名関数とでbenchmarkの外側で定義して実行時コストを比較すべき。
Benchmark: running anon, eval for at least 3 CPU seconds...
anon: 4 wallclock secs ( 3.15 usr + 0.01 sys = 3.16 CPU) @ 1837367.09/s (n=5806080)
eval: 4 wallclock secs ( 3.23 usr + 0.00 sys = 3.23 CPU) @ 1855530.03/s (n=5993362)
Rate anon eval
anon 1837367/s -- -1%
eval 1855530/s 1% --
となってほとんど同じ。
2009/01/14 (水)
■ github で人のコードをいじる「前」にforkする必要はない

git/github を使い始めてほぼ1週間ぐらい。よくできた分散SCMだなぁ、とおもう。とくに rebase とか stash なんか、svk でももちろんできるけどこういう機能が最初からついてるのは素敵。
で、github にプロジェクトをおいておくと fork ボタンがあってすぐに fork していじって commit/push して pull request ってのが素敵なわけだけど、とくにコミットもしないのにとりあえず fork だけしておく、っていうのがたまにみかけるのだけど、それって必要ないよね、って話。(や、別にやるなということではなく、単に勘違いしてやっているのもあるのではないか?と思ったりするので)
Rails on the Run - How to use github and submit a patch とかで、「とりあえず "fork" ボタンをおして fork したレポジトリをつくりましょう」とか書いてあるのでそれが原因なのかもしれないけど、git でとってきたプロジェクトにローカルパッチをあてるのに fork は必要ないです。
git clone git://github.com/miyagawa/remedie.git cd remedie # ファイルを編集 git ci ...
ローカルにある git の作業用ディレクトリは push されるまで remote (origin) とは関係ないので、パッチをあてていくら commit してもまったく問題ない。し、git://github.com/... で clone しているのでそもそも push することはできない。
You can't push to git://github.com/user/repo.git Use git@github.com:user/repo.git
ちなみにこうやってパッチをあてた状態で remote からとってくるときは git pull でなくて git pull --rebase したほうが精神的にいいかもしれない(--rebase はローカルのパッチをいったんなかったことにしたあと pull で最新版にして再度アプライする)。
で、このローカルの変更を master に反映したい(してもらいたい)ときにはじめて、github 上で fork ボタンをおして fork をつくり、git remote add myfork git@github.com:username/remedie.git で remote に追加、git push myfork master で fork に対して push、でもって pull request を送るという手順がいいんじゃないかなとおもう(origin, myfork という名前が気に食わなければ .git/config を編集するなりして upstream, origin という具合に変更すればいいんすかね)。
まぁ fork ボタンを押すことで元の作者に「fork したよ」というメッセージが伝わるので、自分に対するモチベーション/プレッシャーをかけるという意味では先に forkしてしまう、というのもアリかもしれませんがね。