トップ 最新 追記

じじぃの日記、ツッコミ可

Twitter: @jijixi_org
Xbox Live: jijixi

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|11|
2011|05|
2012|01|

2007-11-01 [長年日記]

% [雑談] 中日ファンの人おめでとう

く、くやしくなんかないんだからね!!


2007-11-02 [長年日記]

% [game] アルトネリコ2日記、そろそろ終わりそう編

まあ PHASE5 があったわけだが。つーか PHASE4 が思ったより短かったというか。 で、さすがにそろそろ終わりが近い感じではあるんだけど、ちょっとより道してフレリアさまにダイブ。

変太「年上で魔法使いのドジッ子な妹みたいな恋人を募集中だ。ツンデレなら尚よし、即結婚!!」

無茶言うな……と思ったが、そういやどこぞの塔の管理者は全てあてはまるような気もするぞ。 ちなみにその管理者さまはフレリアにダイブできるようになる直前に、ちょい役で出番が。

% [game] アルトネリコ2日記、より道継続編

ちょwwwボスwwwでんすけスーツ自重www


2007-11-03 [長年日記]

% [Mac] レオパルドン買ってきた

や、やっぱ『ン』は余計じゃないっすか(苦笑

さて、今週末は日本シリーズ観戦に集中する予定だったのだが、みなさんご存知のとおり残念な結果に終わったので予定が崩れたのであった。 で、しかたないので、今日は Leopard へのアップグレードの日にしようと思い立ち、わざわざヨドバシまで行って買ってきたよ。 Mac のコーナーを三周くらいしても目当てのブツが見付けられずに、店員さんに頼んだら「こちらですね?」と持ってきてくれたのが…

「箱小っさ!!」

そりゃ見付からんわけだ。 完全に今までのようなデカい化粧箱をイメージして探してたよ。 まあ、あれってどう考えても邪魔でしかなかったから、これは正解だと思うけども。

そいでもって、他にも予定どおりタイムマシン用に外付けハードディスクを調達。 前に物色したときには、FireWire 付きと USB のみで一万円近く差があったと思ったんだけど、なんか今では二・三千円しか違わないみたいなんで、ホッとしながら 320GB のものをゲット。 Buffalo の白いやつで、冷却ユニットとセットで二万円とちょっと。 安くなったもんだね。

ちなみに Logitec のやつで、もう少し安いのがあったんだけど (二千円ほど安かった)、どうも個人的に Logitec は信用してないので結局 Buffalo の方に。 じゃあ Buffalo を信用してるのかというと、そうでもないんだが、Logitec に比べればという感じで。

そんなこんなで、これからバックアップとアップグレード作業をちまちまやる予定。 まあ、アップグレードというか 10.4 は残しておいて、別パーテーションに新規インストールするつもりだけど。

% [game] アルトネリコ2日記、とりあえず終了編

実は今朝方までかけてクリアしていたのであった。

相変わらず本当の意味での悪人がいない世界だったね。 まあ、クローシェ辺りにはかなりキッツイ過去があったりするんだけど、最終的に報われてるんだから平和な終わり方だと言い切って良いだろう。

エピローグでは三作目への布石なんかもあったりして、ちょっぴり楽しみ。 次はどのハードで出るんだ?という心配はあるが。

二周目特典のようなものは今回も無いようで、前作と同じくアイテム等のデータが蓄積されるのみ。 ただ、今回はトークマターやコスモスフィアの中身が見れるので、前回よりは充実している。

I.P.D は一応全員保護したけど、全員が親衛隊に入る前にめんどくさくなってクリアしてしまった。 つーか、やっぱり強くなりすぎちゃっててラスボスも楽勝だったり。 レプレキアなんぞいらねーじゃん、みたいな。 まあ、楽勝だったのはムスメパワードで『ガード+超』を付けてたせいもある。 これ使うと戦闘が簡単になりすぎるんで、自重した方が良いかも。

最終的にはやっぱり戦闘を楽しめるのは光の御子 (今回はそういう名前じゃないが) だけみたいだね。 こいつばかりはガードを強化しておかないと死ねるから、そういう意味では緊張感あるけど、何度も何度も同じ相手だと飽きるしさー。 グランファンタズムくらいはおまけボスがいてくれても良いよなー。

ともあれ、前作同様秀作だった。 前作が楽しめたなら今回も楽しめると思う。 あと前作ユーザのためのお楽しみがたくさんあるので、やるなら前作も一緒にやった方が吉。

% [Mac] Leopard インストール後

mds が CPU を占拠しててウザい。 nice くらいしてくれよ〜

でも、そのわりに結構普通に操作できてるのは、全体的に軽くなってるということだろうか。

新しくなったフォルダアイコンが激しく気に食わない。 なんだこの GNOME みたいなヒネりのないデザインは。 アプリケーションとかシステムの特殊フォルダアイコンは、単色になったせいでパッと見区別が付きにくいし、なんなのこれ。

とりあえず mds がおさまってくれるまでは大したことできそうにないんで、ちゃんといじるのは明日以降だなー。


2007-11-04 [長年日記]

% [Mac] とりあえず Leopard のステキなところ

ssh を使うと自動的に ssh-agent を動かしてくれるので keychain (Mac のキーチェーンとは別のもの) がいらなくなった。 しかもパスフレーズはキーチェーン (こっちは Mac の) で管理できるので楽ちん。

% [Mac] はたけフリーズ

わしは AquaSKK を使ってるので無縁。

それはともかく、どうやら辞書ファイルが腐ってるのが原因らしいね。 対処法なんかはググればすぐ見付かるからここには書かない。 つーか、わしは対処してないし。


2007-11-05 [長年日記]

% [Mac] Leopard その後

mds がやたら CPU を食い潰すのはサードパーティ製の Spotlight importer が怪しいと思い全部削除してインデックスを作り直した。 どうやら静かになった模様。 つーか、移行アシスタントはもう少し細かい設定ができるようにしてくれないもんか。 危険物までわざわざコピーしてくれなくても良いんだよ……

で、mds の件はほぼ解決したんだが、今度は Developer Tools のインストールでつまづく。 インストール DVD に入ってる mpkg でインストールしようとするとなぜか途中で失敗するので、しかたなく ADC のサイトからわざわざ Xcode3.0 のアーカイブを取得。

「無功なチェックサムです」と言われてマウントできん...orz

何度ダウンロードしても同じなので、ブチ切れてチェックサムはスキップして無理矢理マウント。 普通に見えてるので、さあインストール…… したが、さっきと同じ結果に。

いい加減めんどくさくなってきたので、メタパッケージは使わずに個別にインストール開始。 メタパッケージで失敗していたものも、別に普通にインストールできる。 けっ、腐ってやがる。 結局、JavaSDK だけは読めなくてインストールできなかったけど、とりあえずまあ良いや。

ところが今度はタイムマシンが「ファイルのコピーに失敗した」とか言って失敗するように。 たかだか一個ファイルコピーに失敗したくらいでその後の処理も全部やめちゃうなんて、バックアップツールとしてどうなのよ?と思わなくもないが、ともあれ何度やり直しても失敗するので /Developer はバックアップしない設定に。 どうせ自分でそこに何か入れたりはしないしな。 あと、Library/Caches も除外設定に追加。 もしかしたら、自動で除外してくれてる可能性もあるけど、念の為に。

タイムマシンは、なんかちょっと期待してたのとは違ったなあ。 もっとファイルシステムに深く食い込んでて、変更がある都度に差分をバックアップ…みたいなことしてくれるかと思ったのに。 実際にやってくれるのは、一時間に一度差分バックアップを取るというだけの模様。 まあ、古くなった分の整理 (破棄) なんかを勝手にやってくれるから、面倒なこと考えなくて良いし、便利なことは便利だけど。


2007-11-06 [長年日記]

% [Mac] Leopard にはいろいろ細かい不満はあるが…

手放しがたい機能もあるんで、もう Tiger には戻れないかな。 ちなみに細かい不満としては、

  • Terminal.app が微妙に退化
    • 進化してる部分も多いんだが、euc で使ってても記号の類のカラム幅が化けるのがダサい
  • Finder などの各種アイコンがダサい
    • Finder は Cocoa 化したのか軽くなってるけど、見た目のセンスがなー
  • Finder のアイコン表示、リスト表示、カラム表示の設定が各フォルダで保存されなくなった
    • 各表示法ごとに長所短所があって、場所によって使いわけてたのに、それが保存されないと不便
  • Eijiro dash が動かん
    • まー、これはアップデートに期待
  • Dock のスタック表示は正直ウザい
    • クリックしたときに一覧が出てくれるのはまあ良いが、Dock に収まってるときには黙ってフォルダアイコンを表示しといてくれ
  • VirtualPC はもう対応されないそうですよ
    • さようなら

他にもいろいろあった気がするが、出てこないので、これくらいで。 逆に手放しがたい機能というと、

  • Spaces は軽くて良いね
    • 今まで使ったことのある仮想デスクトップアプリの中では抜群に軽いと思う
    • 今まで ExpertMouse の右上クリックで Expose にしてたけど、これからは Spaces に割り当てちゃっても良いんじゃないかと思った
  • Time Machine もまあ便利
    • 思ってたのとはちょっと違ったけど、まったく何も考えずに放っといて良いというのは楽だ
    • とはいえ、バックアップのありがたみなんて気付かずに済むのが一番幸せなんだが
  • 全体的に高負荷時の応答性が上がってる感じ
    • CPU メーターが満杯の状態でも結構さくさく動かせる
    • 個人的にはこれが一番ありがたいかも。なんせ世代遅れなマシンなもんで

RubyCocoa はいじってみたいんだけど、まだ全然触れてない。 あと Python との連携もかなり強化されてるらしいね。 あー、Objective-C 2.0 も触ってみないとなー。 まだまだお楽しみはこれからだ。


2007-11-07 [長年日記]

% [Mac] うーん、synergys が動かない…

--no-daemon オプションを付ければ動くんだけど、普通にデーモン化させると途端に死ぬ。 どうしたもんかな。

% [Mac] Leopard では NFS の export 設定はどこでやれば良いのだろう?

今までは NetInfo でやってたんだけど、NetInfo manager が無い。 nidump なんかのコマンドも無いみたいだ。

素直に /etc/exports に書けば良いのかなあ。 実は /etc/hosts に相当するものも以前は NetInfo で管理しないとうまくいかなかったんだけど、今回は普通に /etc/hosts に書けばちゃんとわかってくれるんだよね。

うーん、FreeBSD とかをいじってきて憶えた知識をそのまま使えるようになるのは良いんだけど、今まで一生懸命 NetInfo のこと調べたりしたことが過去の遺物になったかと思うとちょっぴりせつない気も……

% [Mac] NetInfo でやってたときと同じく /etc/exports が存在すると自動的に nfsd を用意してくれるようだ

なのは良いんだが、mountd に相当するものがわからなくて、/etc/exports を書き換えたときに反映させる方法がわからん。 rpcinfo -p localhost とやると mountd (に相当するもの) は存在してるようなんだけど、実際どのプロセスがそうなのかわかんないから HUP を送ることもできない。 めんどくさくなってシステムごと再起動しました(ダメっぽい

ちなみに /etc/exports には Mac OS X ならではの拡張がされてるっぽくて、

/Volumes/Hoge/Fuga -maproot=0:0 -fspath=/Volumes/Hoge

こんな風に書いておくと、/Volumes/Hoge は / とは別のファイルシステムのマウントポイントだと認識してくれて、もしここにディスクがマウントされてないときには、nfs クライアントからの接続をはじいてくれるらしい。 試してないけど。 まあ、詳しくは man exports を。

つーか、FreeBSD だと man exports には /etc/exports を書き換えたら mountd に HUP シグナルを送れと書いてあるんだが、Max OS X の man だと、それに相当する部分が見当たらないんだよなー。

% [Mac] そういえば Spotlight で Safari のキャッシュがヒットするようになってるみたいだね

表示するときにはキャッシュじゃなく URI を実際に読みに行っちゃうみたいだけど。 ともあれ、Spotlight も着実に進化してるということで。


2007-11-09 [長年日記]

% [clip][Rails] ActiveScaffold プラグイン

なんか色々楽できそうなもの。

% [雑談] 今朝から vim が突然死する問題に悩まされている件

何かのキーを押した瞬間、SEGV を起こして死ぬ。

最初は ssh 経由で動かしている FreeBSD の gvim-gtk2 で起こってたので、昨日こいつをアップグレードした影響かと思ってたんだが、どうも Mac 上の vim (http://sourceforge.jp/projects/splhack/ の最後の Carbon 版) でも起こるので、そういうわけでもないみたい。

で、起こる起こらないの条件を調べてみると、

  • FreeBSD (Mac から ssh の X Fowarding で)
    • vim → 起こらない
    • gvim → 起こる
  • Mac
    • vim(上記版付属のスクリプト使用) → 起こる
    • vim(システム付属版) → 起こらない

てな感じで、どうも Mac のキーイベントが変なのではないかという気がする。

昨日までは何ともなかったのに…… と考えると、怪しいのはこれを入れたことなんだが……

入れたは入れたけど、Safari が起動できなくなったんで、結局外したんだよね。 入れたファイルは消してプロセスは殺したし、念の為システムの再起動もしたんだけど、それでも何か影響あるってことあるのかなあ? でも他に原因が思いつかない。 あと可能な対処ってキャッシュの破棄とかか?

とにかく、vim がまともに動いてくれないと仕事にしろ私生活 (というか日記書き) にしろ非常に悪影響が出るので早いとこ何とかせねば。

% [vim] vim の突然死問題、続き

Library/Caches を捨てて再起動しても現象は変わらず。 で、いろいろいじってるうちに、高確率で再現できる操作を見付けた。

  1. 適当に何か書く
  2. Shift+U (行ごとのアンドゥ) 連打 (押しっぱなしでも可)

これで死ぬ。

確認のため FreeBSD の vim で試してみると、(さっきは死なないと書いたが) 同じように死ぬことがわかった。 これはどうやら vim のバージョンの問題っぽいな。 ちなみに問題が起こってるバージョンは、

  • FreeBSD -> 7.1.145
  • Mac -> 7.1.135

試しに 7.1.87 と 7.1.56 を持ってきて同じ操作を試してみると…… 死なない。

どうやら少なくとも patch 7.1.87 から 7.1.135 までのどれかがバグを仕込んでる可能性が大。 とりあえず、Mac では 7.1.87 を使っておけば解決だな。 FreeBSD はどうしよう? むしろこっちの方が痛いんだが、パッケージのバックアップ取ってなかったから、古いの作るのめんどいなー。 やっぱ /usr/local/etc/pkgtools.conf に

PORTUPGRADE_ARGS = ENV['PORTUPGRADE'] || '--backup-packages'

とか書いとくのは必須かねぇ。

とりあえず今回は vim の Makefile の PATCHLEVEL を書き換えて無理矢理ごまかすかな。


2007-11-12 [長年日記]

% [clip][Ruby] Pattern Matching in Ruby (The Scariest Fun : notes from a web startup)

via programming reddit.

こういう遊びは好きだなあ。 とりあえず、これが require してる ruby-debug とやらが何物か知らなくて動かせてないんだけど、サンプルコードを見るかぎり、結構よくできてる感じ。

で、これの構築には dsl.rb というのが使われていて、以前ちょっと話題になった気がするんだけど、きちんとチェックしてなかったので良い機会だしさらっと読んでみた。

そんで let の定義が気に入ったので、やってることの確認のために単純化したものを自分で書いてみたのが以下。

% cat let.rb
module Let
   def let(assigns = {}, &block)
      scope = Object.new
      assigns.each do |name,value|
         scope.instance_eval("def #{name}; @#{name} end")
         scope.instance_variable_set("@#{name}",value)
      end

      scope.instance_eval(&block)
   end
end
% irb
irb(main):001:0> require 'let'
=> true
irb(main):002:0> include Let
=> Object
irb(main):003:0> let :x => 1, :y => 2 do
irb(main):004:1*   p x + y
irb(main):005:1> end
3
=> nil

本物はもっと色々細かいこともやってるけど、まあ基本的な部分はこんな感じかと。 なんかおもしろいので、もう少しいじってみよう。

% [Ruby][雑談] Array#[1..-1]

何日か前から ruby-list で議論されてる件。

わしもこれを添字を使わずに表わすメソッドは前から欲しいとは思っているが、head/tail をあてはめるのはちょっと好きじゃないかな。 head/tail はそもそも cons セルのようなものをイメージした名前じゃないかと思うんだよね。 関数型言語のリストは先頭要素 (head/car) とそれ以外 (tail/cdr) からできている構造だというのが基本だけど、Ruby の配列はそうではないので、ちょっとイメージ合わないなと。 Ruby には first や last というメソッドがあるんだから、その辺から連想した方が良いように思う。

…… てことで、わしもいくつか考えて ruby-list に送っちゃろうと思ったんだけど、いまいちこれだっていうのが無くて結局ここでつぶやくだけにしとくことにした(弱

  • first(-1)
    • 意味がどうのより、使われてない領域を有効活用するという方向性。
  • last(-1)
    • 同上。どっちにしても -1 というのは直感的ではない気はするが。
  • unfirst/nofirst/nonfirst
    • first 以外というニュアンスの造語。キモいかな。
  • after_first
    • first より後ろ。
  • rest/remainder
    • 残りという意味合い。これは誰かが提案してた。
    • rest だと休養という意味の方が有名な気がするので、remainder の方が良いかなと思ったが、今度は剰余とごっちゃになって良くないかも。

単語としてはキモいかもしれないけど、unfirst のような系統が意味も憶えやすく適度に短いので良いような気はしてる。 かと言って、これにしようぜ〜とメーリングリストに投げるほど自信があるわけでもないんだが……

% [Ruby] パターンマッチの続き

ソースを読むかぎり ruby-debug が必要になっている部分がよくわからんので、試しに require をコメントアウトしてみたら、なんだ普通に動くではないか。 消し忘れか何かか?

まあとにかく動くようなので試す。 dsl.rb はすでに存在している前提で。

irb(main):001:0> require 'pattern_match'
=> true
irb(main):002:0> include Matchable
=> Object
irb(main):003:0> def fib(n)
irb(main):004:1>   match n do
irb(main):005:2*     with(0) { 0 }
irb(main):006:2>     with(1) { 1 }
irb(main):007:2>     otherwise { fib(n-1) + fib(n-2) }
irb(main):008:2>   end
irb(main):009:1> end
=> nil
irb(main):010:0> fib(10)
=> 55

ふむ。

irb(main):015:0> match [1,2,3] do
irb(main):016:1* with([:x,:y,:z]) do p x,y,z end
irb(main):017:1> end
1
2
3
=> nil

ふむふむ。

irb(main):024:0> match [1,2,3] do
irb(main):025:1* with(:x % :xs) { p x, xs }
irb(main):026:1> end
1
[2, 3]
=> nil
irb(main):027:0> match 'hoge' do
irb(main):028:1* with(:x & String) { p x }
irb(main):029:1> end
"hoge"
=> nil

結構自然な表記になっててすごいなあ。 なんか常用したくなりつつあるわしがいる(苦笑

ところで dsl.rb にはセットで comprehension.rb というものもあって、これはその名のとおり内包表記を実現するものだ。

irb(main):030:0> require 'comprehension'
=> true
irb(main):031:0> with Comprehension::DSL do
irb(main):032:1*   list { x * 2 }.given(:x => 0..5) { x > 3 }
irb(main):033:1> end
=> [8, 10]

このように使う。 見た目はちょっとキモいけど、ちゃんと内包表記っぽく動くので大変すばらしい。

% [Mac] Leopard の Dictionary.app にさりげなく英和・和英辞典が含まれててのけぞった

なにげなく Preference 覗いてみてびっくりしたよ。 こいつらを有効にして、パネルが開くように設定すれば、いろんなところでコンテクストメニューから辞書が引けて便利。

英辞郎のファイルを Dictionary.app 用に変換するとかいうネタもどこかで見たけど、とりあえずそんなめんどうなことしなくても、素の状態でそれなりに役に立ってくれるね。


2007-11-13 [長年日記]

% [Python] contextlib -- Utilities for with-statement contexts.

programming reddit 経由で見た記事で見かけて、こんなものがあったのか… と調べてみた。 要するに with 構文のためのユーティリティ。

  • contextmanager
    • 自動的に __enter__ と __exit__ を定義してくれるデコレータ
  • nested
    • ネストした with 文をまとめてくれる
  • closing
    • 自動的に close メソッドを呼ぶような __exit__ を定義してくれる
In [1]: from contextlib import contextmanager,nested,closing
In [2]: @contextmanager
   ...: def hoge(a,b):
   ...:     print a
   ...:     yield
   ...:     print b
   ...: 
In [3]: with hoge('foo','bar'):
   ...:     print 'baz'
   ...: 
foo
baz
bar

こんな感じで、yield の前を __enter__ 、後を __exit__ 相当にしてくれる。

In [4]: with nested(hoge(1,2),hoge(3,4),hoge(5,6)):
   ...:     pass
   ...: 
1
3
5
6
4
2

これは以下のようなのと同じこと。

In [5]: with hoge(1,2):
   ...:     with hoge(3,4):
   ...:         with hoge(5,6):
   ...:             pass
   ...: 
1
3
5
6
4
2
In [6]: class Hoge:
   ...:     def close(self):
   ...:         print 'close!'
   ...: 
In [7]: with closing(Hoge()):
   ...:     print 'hoge'
   ...: 
hoge
close!

__exit__ に相当する部分で close を呼んでくれてる。

with 構文を使う上でかなり有用な感じなので、憶えておいた方が良さそう。


2007-11-14 [長年日記]

% [雑談] 車検費用

はあ…… 13 万か。高いなあ。

まあ、一応 15 万用意してたから想定の範囲内ではあるんだけど、できれば 10 万くらいで済んでほしかったよ。 つーか、それくらいで済んだらちょっと無駄遣いしてみようと思ってた (具体的には某 touch とか) んだけど、夢は破れたなー。

もう買ってから 7 年経つし、雪国はどうしても下回りの劣化が激しいので (主に融雪剤の影響)、しかたないっちゃーしかたないんだが。 かといって、買い替えるような余裕もしばらく無さそうだし、無理に安く上げるよりはちゃんと金かけて整備してもらった方が良いだろう。

% [Ruby][Rails][MySQL] ごくごく基本的な Ruby on Rails のパフォーマンスチューニング

Ruby は知ってるけど、MySQL とかその他のデータベースアプリはほとんど使ったことなんて無い…… という人 (それはわし) が、いきなり Rails で何かを作り始めたときにやってしまいがちな失敗。 それが、

  • script/generator model が出力したまんまのテーブルを使い続ける

というやつ。 わしは今のところ MySQL しか使ったことが無いので、とりあえず以下は MySQL だけを例にして書くが、

  • MySQL は、インデックスを持たないカラムをキーにした場合、線形探索になる

という事実がある。 MySQL を使っている人には自明のことなのかも知れないが、そうじゃない素人にとっては、それはわりと想定の範囲外だったりする。 というか、明示的に作成しないかぎり、プライマリキー以外にインデックスが存在しないということが、そもそもわからない。

そうするとどうなるかというと、簡単なサンプルを作っているうちは良いのだが、10 万、100 万といった数のレコードを持つテーブルを使う段になって破綻する。 まさかそんな数のレコードを、Hoge.find :all で全部取得するようなアホはいないはずで、当然何かしら :conditions オプションでもってふるいをかけるだろう。 だが、その :conditions にプライマリキー (Rails において、それは id と決まっている) 以外を使っていれば (もちろん当然使わざるを得ないんだが) ものすごく検索が遅くなる。 ともあれ、

  • :conditions オプションでキーに使われるようなカラムにはインデックスを作成すべし

である。 ちなみにこれは migration ファイル (db/migrate 以下) で、

add_index テーブル名, カラム名

とすることで追加できる。 例えば

% ./script/generator model person name:string age:integer

てな感じで作ったモデルであれば、Person というクラスと people というテーブルができているはずなので、ここで作られた migrate ファイルでも良いし、新たに作ったものでも良いから self.up に

add_index :people, :name

と書けば良い。 ちなみに self.down には、

remove_index :people, :name

と書いておく。

あと、MySQL の場合は複数のカラムをキーに検索する場合には最初に使われるカラムのインデックスしか使われないという制限があって、そこを何とかするために複合インデックスという仕組みが存在している。 これは要するに、上のようなモデルで、

Person.find :all, :conditions => ['name = ? AND age = ?', 'hoge', 10]

みたいな条件を指定したときには、例え age カラムにインデックスが存在してもそれは使われないということで、こういう場合に age でもインデックスが使われるようにしたいなら複合インデックスを用意しなさいということ (まあ、上記のようなシチュエーションなら、name の条件で十分小さい数まで絞り込めそうなんで、あまり気にすることはないだろうけど)。 複合インデックスは以下のように作れる。

add_index :people, [:name, :age]

この場合 remove_index は書き方がちょっと変わるので注意。

remove_index :people, :column => [:name, :age]

ともあれ、複合インデックスについては MySQL のマニュアルをよく読んだ方が良い。 あと、上記のやり方で作成するときには指定した各カラム名から、インデックスの名前が自動的に決定されるんだが、それがあまりに長すぎると MySQL 側でエラーになる場合がある。 そんなときは自分でインデックス名を指定してやると回避できる。

add_index :people, [:name, :age], :name => 'index_hoge'

この場合の remove_index は以下。

remove_index :people, :column => [:name, :age], :name => 'index_hoge'

さて、データベース側の話はとりあえずこれくらいにして、Ruby としての話も少し。

わりとよく言われる Ruby におけるパフォーマンスチューニング法に、

  • GC の回数を減らす

というのがあると思う。 これは要するにメモリの使用量を最小限にしろ… というのとほぼ同義だと思うが、ActiveRecord というやつは結構富豪的な作りというか、何も考えないで find すると SQL 的には SELECT * FROM ... で全部のカラムを持ってきてそれをきっちりインスタンスに詰めてよこすようになっていて、これが積み重なると結構な無駄になっていると思われる。

これはデータベース側にとっても結構無駄が多くて、例えば name というカラムが必要なだけであれば、当然のように SELECT name FROM ... という SQL 文を書きなさいという話になるはず。 で、ActiveRecord でこれをやるには :select オプションを使う。

Person.find :all, :select => 'id,name', :conditions => 'age > 10'

とか書くと、age が 10 より大きいレコードが、id と name カラムだけを持ってインスタンス化される。 別に :select のところは 'name' でも良いけど、大抵の場合 id も無いと困るので、入れておいた方が無難。 あと、この :select オプションは find だけじゃなく最終的に find と同じようにクエリが発行されるものであれば大抵は使えるので、例えば has_many や belongs_to の指定時などにも使える。

has_many :friends, :select => 'id,name'

みたいな感じで。

インデックスの話もそうだけど、この :select に関しては入門記事なんかにはあまり書いていないことが多くて、ある程度 Rails に慣れてからハマる人ってそれなりにいるんじゃないかなーと思ったりした。 あと、自分で SQL を書くならちゃんと必要なカラムだけ SELECT するのに、ActiveRecord でもそれができることに気付かずに放置してる、なんて人もいるかも。

あと余談。

script/server をフォアグラウンドで動かしつつ、別の端末で script/console を動かせば、find などが発行するクエリがどんな風になっているかリアルタイムに確認できて便利。 has_many なんかが、ちゃんとクエリの発行を遅延させているところなんかも確認できる。 例えば、

class Hoge
  has_many :fugas
end

みたいなモデルがあったとして、

>> hoge = Hoge.find :first
>> hoge.fugas; nil

とか、

>> hoge.fugas.find :first; nil

みたいなことをやってみると良い。 けっして hoge.fugas の時点で SELECT * FROM fugas WHERE (fugas.id = 1) みたいな富豪的なクエリが発行されているなんてことは無いのがわかるはず。 ちなみに、いちいち ; nil などと付けているのは、そうしないと irb が値を表示させるためにせっかく遅延されてるクエリが発行されてしまうから。

何はともあれ、Rails でちゃんとしたアプリケーションを作りたいなら、結局データベースに関する知識は必要だよ、という話かな。

本日のツッコミ(全2件) [ツッコミを入れる]

% drkazu [車検取って2か月して、車がだめになりましたです。。]

% jijixi [それはツラい。 わしは車検取って一ヶ月で、衝動的に買い替えたってことはありましたが(苦笑]


2007-11-16 [長年日記]

% [雑談] 久しぶりにマニュアル車を運転した

代車で。

今の車に換えてから 7 年間、ほとんどマニュアルなんて乗ってないんだけど、別に普通に運転できるもんだね。 自転車とかスキーとかって一回乗れるようになればブランクあっても普通に乗れるって言うけど、自動車もそういうもんか。 まあ、ちょっと坂道発進のときにドキドキするけど。


2007-11-17 [長年日記]

% [Ruby] assign_utilities

本日の日曜プログラム。土曜だけど。

最近仕事は Ruby 一色なんで、たまに他の言語で何か書こうと思ったんだけど、なぜか結局 Ruby をいじってしまってるのは呪いなのか。

ともあれ、今日はこの前の dsl.rb ネタで書いた let メソッドを、もう少しちゃんと使えるようにしてみた。 具体的には、

  • インスタンス変数もそのまま使えるように
  • self が謎のインスタンスになっちゃうのを何とかする

というような感じ。 まあ self の問題は仕組み上ちょっと難しいので、代わりに this というメソッドを用意してごまかした。

最初は単にお遊びのつもりで始めたんだけど、なんか途中でちゃんと自分で使えそうな気がしてきたんで、思わず gem とか作ってみた。 そこそこマジメにテストも書いた。 こちら↓

あとは、以下、使用例とか。

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'assign_utilities'
=> true
irb(main):003:0> @hoge = 'hoge'
=> "hoge"
irb(main):004:0> def foo
irb(main):005:1>   p 'foo'
irb(main):006:1> end
=> nil
irb(main):007:0> let :fuga => 'fuga' do
irb(main):008:1*   p @hoge + fuga
irb(main):009:1>   this.foo
irb(main):010:1> end
"hogefuga"
"foo"
=> nil

こんな感じ。

で、実のところこれは本題ではなくて、ほんとは scheme の let-keywords のようなものが作りたくて、let を整備したんである。 名前はそのまま let_keywords でも良かったんだけど、それも芸が無いので assign_keywords という名前にした。 長くなってるやん。

や、一応 Object に include するので、あんまり短い名前にすると迷惑になるかと思ってさ。 短くしたい人は alias すれば良いんだし。 ともあれ、こんな風に使う。

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'assign_utilities'
=> true
irb(main):003:0> def f(kw = {})
irb(main):004:1>   assign_keywords kw, :name => '', :age => 0 do
irb(main):005:2*     p name, age
irb(main):006:2>   end
irb(main):007:1> end
=> nil
irb(main):008:0> f()
""
0
=> nil
irb(main):009:0> f(:name => 'hoge', :age => 10)
"hoge"
10
=> nil
irb(main):010:0> f(:hoge => 'hoge')
ArgumentError: Unknown keywords found: hoge
 from /Library/Ruby/Gems/.../lib/assign_utilities/assign_keywords.rb:50:in `check_keywords'
 from /Library/Ruby/Gems/.../lib/assign_utilities/assign_keywords.rb:15:in `assign_keywords'
 from (irb):4:in `f'
 from (irb):10

assign_keywords に渡すブロックは基本的にはさっきの let と同じ扱い。 キーワード引数としてハッシュを受け取って、指定したキーワードのみ受け付けるようになっている。 指定してないキーワード (ハッシュのキー) が使われてたら例外。 ちなみに、どうして例外が上がるようにしたかというと、Rails でハッシュのキーを typo ってうまく動かないのに、原因がなかなか見付けられずに難儀した経験から。 例外上げたくない人は、こんなもん使わずにハッシュのまま処理してくださいな(苦笑

受け付けるキーワードの指定にハッシュを使えば、上記のとおりデフォルト値の指定になる。 デフォルト値が必要無ければ、キーワード名だけ羅列しても良い。

irb(main):011:0> def g(kw = {})
irb(main):012:1>   assign_keywords kw, :name, :age do
irb(main):013:2*     p name, age
irb(main):014:2>   end
irb(main):015:1> end
=> nil
irb(main):016:0> g()
nil
nil
=> nil
irb(main):017:0> g(:name => 'fuga')
"fuga"
nil
=> nil

ブロックを与えない場合は、キーワードに対応したアクセサだけが定義されたオブジェクトが返る。

irb(main):018:0> obj = assign_keywords({:hoge => 'hoge'}, :hoge)
=> #<AssignUtilities::AssignedKeywordsObject:0x120d6bc ...
irb(main):019:0> obj.hoge
=> "hoge"
irb(main):020:0> obj.fuga
NoMethodError: undefined method `fuga' for ...
 from (irb):20
irb(main):021:0> obj.to_hash
=> {:hoge=>"hoge"}

とりあえず、今のところはこの let と assign_keywords の二つだけだけど、 なんか、こういうの作ってると妙に楽しいので、もう少しいろいろ追加してみたいところ。 次は何が良いだろねぇ。


2007-11-18 [長年日記]

% [Ruby] partial_proc

assign_utilities に追加した。 scheme の cut のようなもの。

使用例。(あらかじめ 'rubygems' と 'assign_utilities' は require 済み)

irb(main):001:0> f = Proc.new do |a,b,c|
irb(main):002:1*   p a,b,c
irb(main):003:1> end
=> #<Proc:0x01257050@(irb):1>
irb(main):004:0> g = f.partial(:_,2,:_)
=> #<Proc:0x0124e6bc@/Library/Ruby/Gems/.../assign_utilities/partial_proc.rb:16>
irb(main):005:0> g.call(1,3)
1
2
3
=> nil
irb(main):006:0> def foo(a,b,c)
irb(main):007:1>   p a,b,c
irb(main):008:1> end
=> nil
irb(main):009:0> m = self.partial_method(:foo, 1,:_,3)
=> #<Proc:0x0122a618@/Library/Ruby/Gems/.../assign_utilities/partial_proc.rb:16>
irb(main):010:0> m.call(2)
1
2
3
=> nil

こういうのやるときは、どうしても eval 系を多用することになっちゃって微妙。 楽しいことは楽しいんだけど、なんか背徳感を感じるというか(苦笑


2007-11-19 [長年日記]

% [Mac][Ruby] Developer Tools を再インストール

RubyCocoa で遊ぼうと思って、CocoaRepl や RubyConsole をビルドしようと思ったんだけど、どっちもビルドに失敗する。 どうやらこの前むりやりインストールした影響なのか、どっかぶっこわれているらしい。

で、しばらく放置してたんだけど、ふと思ってもう一度 ADC から Xcode 3.0 のパッケージをダウンロードしてみたところ、うまい具合に正常にマウントできたのであった。 10.5.1 になったおかげなのか、ファイルが差し換えられたのかは不明だが。

ともあれ、Developer Tools については正常にインストール完了。 今まではなんとなくすっきりしない状態だったので、とりあえずホッとした。 でも、結局 CocoaRepl と RubyConsole の問題は解決せず。 CocoaRepl はリンクエラーが出てて、RubyCocoa の方はビルドは完了するけどまともに起動しない。

てなところで、めんどくさくなったんでまた放置。


2007-11-20 [長年日記]

% [clip] 薄型TVの弊害 (アルファルファモザイク)

写真自体は、やらせだと思うけど TV の上が猫にとって大事なお気に入りポイントなのは確か。


2007-11-21 [長年日記]

% [Ruby][Python] 文字列の均等分割 (DouKaku?)

きむらさんとこ経由で。

昨夜、なんだか眠れなくて暇つぶしに書いたので投稿しておいた。 #4281 がそう。 別にエレガントでもないし、短いわけでもない。 アプローチも投稿済のものと同じみたいだし、何も特徴が無いものだったっす。 算術演算を使わず、文字列の長さを測ることもせずに…… となると、これくらいしか思いつかなかったけど。 まあ、さすがにインクリメントくらいは許してもらったが(苦笑

ざっと回答を眺めてみた感じ、greentea さんの #4264 が好みだった。 もう少し粘れば len を消せるんじゃないかって気がするんだけど、ちゃんと考えてはいない。

DouKaku? には登録したんだけど、ログインができなくてアカウントは使ってない。 つーか、もしかしたら確認メールが届いてアクティベート… っていう仕組みなのに、そのメールが届いてないってパターンかなあ? パスワード忘れの手続きしてもメール届かないし、どっかでブラックホールに落ちてるのかも。

別のアドレスで新しくアカウント作ってみるかねぇ……

% [Ruby][雑談] Integer#succ とか Integer#next ってのはあるのに

pred も prev も無いなんて……

いや、そんなもの普段は無くても良いけどさ…… 今はちょっと使いたかったのよ……ぐすん。

% [Ruby][DouKaku] 文字列の均等分割、失敗作

#4264 を元に len() を消す方向でできないかな〜とやってみた (Ruby だけど) んだが、失敗だった。おしい。

require 'pp'
sample = 'ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく'

def split_str(len, str, limit, acc = [])
   if limit.zero? and str.nil?
      acc
   elsif limit.zero? or str.nil?
      nil
   else
      split_str(len, str[len..-1], limit - 1, acc << str[0...len])
   end
end

def divid_(num, str, count)
   raise ArgumentError if str[count].nil?

   if (ary = split_str(count, str, num))
      ary.map {|a| a.join}
   else
      divid_(num, str, count + 1)
   end
end

def divid(num, str)
   divid_(num, str.split(//), 0)
end

(4..6).each do |n|
   pp divid(n, sample)
end
["ゆめよりもはかなき世のなかを",
 "なげきわびつゝあかしくらすほ",
 "どに四月十よひにもなりぬれば",
 "木のしたくらがりもてゆく"]
["ゆめよりもはかなき世の",
 "なかをなげきわびつゝあ",
 "かしくらすほどに四月十",
 "よひにもなりぬれば木の",
 "したくらがりもてゆく"]
["ゆめよりもはかなき世",
 "のなかをなげきわびつ",
 "ゝあかしくらすほどに",
 "四月十よひにもなりぬ",
 "れば木のしたくらがり",
 "もてゆく"]

ちょっと安易すぎたかな……

% [Ruby][雑談] そういえば、Array#[1..-1] の代わりになる書き方には…

こういうの↓ もありますぞ。 わしは結構使う。

irb(main):001:0> a = (1..5).to_a
=> [1, 2, 3, 4, 5]
irb(main):002:0> hd, *tl = a
=> [1, 2, 3, 4, 5]
irb(main):003:0> hd
=> 1
irb(main):004:0> tl
=> [2, 3, 4, 5]

ちょっとパターンマッチっぽいのが好き。

% [Ruby][DouKaku] 文字列の反転(括弧の対応を保存)

新たにアカウントを取ったので、名前付きで投稿した→ #4300

真っ平らにする flatten を活かすために、わざと結果の配列がネストしまくるように書いてみた。 まあ、この場合は、余計なこと考えなくて良いから楽かもしれん。 でも、ネストの段数を考えるクセが付いてるので (OCaml とかだと、そうじゃなきゃ書けんからね)、むしろ疲れた(苦笑

テストデータを問題文からコピペしたんだけど、最後の例だけどうしてもパスしなくてしばらく悩んだ。 で、expected と result を並べて表示するようにしてようやく気付く。 問題文の例が間違っとる...orz

句点が足りてないというオチだった。

しかし、これ書くのに一時間以上かかっちゃってるわしって大丈夫なのかなあ? 30 分もあれば書けるだろ… と思って始めたのに、全然思ったとおりに進まないし、自信無くす……


2007-11-22 [長年日記]

% [雑談] 巷で話題の http://speedtest.10-fast-fingers.com/ をやってみたが、結果を表示する段階で Safari が落ちた件

テラションボリ。

たぶん 50 個くらいは行ったと思うんだけど。 まあ、あんまり難しい単語が出てこないので、わしのように英語力が微妙 (婉曲表現) な人間にも何とかなるレベルではあるような。

sometime とか someone とか somewhere とかで、つい some のあとにスペース押しちゃうクセは、以前から気にしてたんだけど、こういうゲームでは思いっきり障害になるな(苦笑

ともあれ、タイピングゲームとかって別に好きでも何でもないんだけど、これは何というか進み方が小気味良いんで結構楽しかった。 まあ、一回やれば十分だけど。

% [Gauche][Scheme][DouKaku] 文字列の反転(括弧の対応を保存)

たまに無性に Scheme のコードを書きたくなることがある。 なので、昨日の Ruby のコードを移植。→ #4341

相変わらず util.match 使いまくり。 つーか、これ無しで書くなんて考えられない。

最初はもっと完全に直訳でいけると思ったんだけど、Array#flatten の代替が見あたらなくて断念。 flatten の真っ平らにする挙動って LISP 由来だと思ってたんだけど、Scheme には無いのかね。 CommonLisp にはあるのかな。

format の第一引数を省略したときの挙動を勘違いして、省略すると #t だと思い込み、「変だな〜何も表示されないな〜」と悩んだのは内緒だ。

% [Gauche][Scheme][DouKaku] 自然数の分割

さっきので Gauche のリハビリが完了したので (元々大したレベルじゃないけど) 今度は元ネタ無しでチャレンジ。→ #4344

リストのネスト段数の辻褄がなかなか合わせられなくて死亡...orz

やっぱ、こういうの書くときは静的型付け言語の方が楽だと思う。 で、ぐちぐち文句良いつつなんかものすごく時間かかって、ようやく完成させて、えいやっと投稿して、そして……

#4317 を見て絶望...orz

本日のツッコミ(全2件) [ツッコミを入れる]

% shiro [CLにも無かったと思います。Lisp/Schemeではリストにタプル、シーケンス、集合、連想リストなどいろいろな意味..]

% jijixi [なるほど。 > リストにタプル、シーケンス、集合、連想リストなどいろいろな意味を持たせていて Ruby でも状況..]


2007-11-23 [長年日記]

% [OCaml][DouKaku] #4346 (自然数の分割)

Scheme 版のほぼまんま。 というか、いつものことだけど、Scheme のコード書くときは基本的に OCaml 脳になってるので、わしの書く Scheme のコードはかなりの確率でそのまんま OCaml に変換できるという。

OCaml のコードなんて、もう何ヶ月もまともに書いてない気がするけど、驚くほどスラスラ書けてしまって、われながらちょっとびっくりした。

% [clip][Erlang] Erlang String Lambdas (Ruminations of a Programmer)

via programming reddit.

文字列から関数 (クロージャ) を作るモジュールを作ったよという話。おもしろい。

erl_eval 系モジュールの使い方がマニュアル読んでもイマイチしっくり来てなかったので、これのソース見つつ勉強しようかな。 とりあえず、一番シンプルな使い方は lib_lambda.erl の eval 関数がそれっぽい。

eval(S) ->
    {ok,Scanned,_} = erl_scan:string(S),
    {ok,Parsed} = erl_parse:parse_exprs(Scanned),
    {value, Value,_} = erl_eval:exprs(Parsed,[]),
    Value.
Eshell V5.5.5  (abort with ^G)
1> S = "io:format('hoge~n').".
"io:format('hoge~n')."
2> {ok, Sc, _} = erl_scan:string(S).
{ok,[{atom,1,io},
     {':',1},
     {atom,1,format},
     {'(',1},
     {atom,1,'hoge~n'},
     {')',1},
     {dot,1}],
    1}
3> {ok, Ps} = erl_parse:parse_exprs(Sc).
{ok,[{call,1,{remote,1,{atom,1,io},{atom,1,format}},[{atom,1,'hoge~n'}]}]}
4> {value, Val, _} = erl_eval:exprs(Ps, []).
hoge
{value,ok,[]}

ほほう。

% [JoCaml][DouKaku] 分散関数呼び出し

JoCamlってのはナニモノ?」って声が聞こえてきてセツなかったので、JoCaml で投稿してみた。→ #4375

まーなんつーのか、ググっても日本語のページはわしの日記くらいしか出てこないあたり、実は誰もいじってないのかしらと心配なんだが、どうなんだろね。 programming reddit なんかを見てると、海外ではじわじわ人気が出てきてるようにも思えるんだけど。


2007-11-24 [長年日記]

% [JoCaml][DouKaku] #4381 (正しい文(クイズ))

前に Erlang でやったことがある、全部のパターンを一気に並行処理して、どれか答が返ってきたらとっとと終了というのを JoCaml で書いてみた。

…… んだが、システムスレッド数の問題で 5 進数くらいまでしか計算できず。 プロセス自体はシステムスレッドよりも多く起動できるんで、プログラムが落ちるわけじゃないんだけど、多分処理待ちでブロックするプロセスがスレッド数を越えちゃうせいで、実質デッドロックになるんだと思われる。 ちなみにうちの環境 (Mac OS X 10.5/ppc64) だとシステムスレッド数の上限は 2560 らしく、それ以上は増えない。

とりあえず、プロセスを富豪的に使いすぎてる部分があるんで、そこをちょっと工夫すればもう少し余裕ができるかもしれないけど、やっぱこういうことやるなら Erlang の方が良いのかも知れず。

% [Erlang][雑談] Programming Erlang (ペーパーバック) ゲット

ちょっとそこらで売ってなくて、Amazon でマンガを頼んだんだけど微妙に 1,500 円に満たず、どうしたもんかな〜と考えたときに、ふと「良い機会だし」と思い付いて注文してたのが届いた。 一括発送なんでマンガの方の入荷待ちだったから、いつになるかわからん状態だったんだけど (注文時には 12 月中旬になってた) なんか今日来たのであった。

いやー、全部英語だね。(あたりまえです

積読になりそうな気配は十分だけど、とりあえずパラパラ眺めた感じ 10 章くらいまではわりと今さらなネタっぽいので、読むとしたらそれ以降を重点的に攻めることになるかな、という方向。

% [雑談] ところで全然関係無いけど……

一緒に (別口で注文していた) ぽて DVD の 3 も届いていたり。 今回も初回特典は順調に必要無いので (ぉぃぉぃ) 最終巻まで溜め込んだ後、某氏にまとめて送り付けちゃろうと目論見中。

% [clip][Ruby][DouKaku] shinh さんの回答 (#4382) (正しい文(クイズ))

なんかスゴイみたいなんだけど、何やってんのか全然わかりません(苦笑

5 とか 4 とか 99 とかってどっから出てきたんだろ? つーか、その前にゴルフくささを薄める方向に清書しないと読むのもままならないっす。

誰か解説してくれないかな。

本日のツッコミ(全6件) [ツッコミを入れる]

Before...

% jijixi [よく見たら発売日もうすぐじゃないですか。 でも買うかどうかは中身見てからかなー。]

% cooldaemon [噂によると Programming Erlang の翻訳も進んでいるらしいですよ。]

% jijixi [原書を買ってしまった今となっては、個人的な意味は微妙ですけど、日本語の入門書が増えることでユーザが増えてくれれば良い..]


2007-11-25 [長年日記]

% [Ruby][DouKaku] なんか shinh さんが反応してくれたので

とりあえず自分にとって読みやすくなるように清書してみた。

 1 def x(base, acc, num, end_point, count)
 2    if base == num
 3       if acc == end_point
 4          puts (0...base).map { |i|
 5             "#{i.to_s(base)}*#{acc[i].to_s(base)}"
 6          }.join(', ')
 7       end
 8    else
 9       limit = 
10          if base < 5
11             5
12          else
13             _a = if num > 1
14                     [4 - num, 0].max + end_point[num]
15                  else
16                     99
17                  end
18             _b = base + 2 - count + num
19             [_a, _b].min
20          end
21 
22       1.upto(limit) { |i|
23          acc[num] = i
24          new_end = end_point.dup
25          i.to_s(base).scan(/./) { new_end[$&.to_i(base)] += 1 }
26          next if (0..num).any? { |j| new_end[j] > acc[j] }
27          x(base, acc, num+1, new_end, count+i)
28       }
29    end
30 end
31 
32 2.upto(16) { |base|
33    p base
34    x(base, [0]*base, 0, [1]*base, 0)
35 }

変数名は適当に長い名前に直した。 base が基数、acc は今確かめようとしているパターン、num は数えようとしている数字、end_point は実際に数字を数えたもの、count はなんかちょっとよくわからない数字。

基本的なアルゴリズムは、総当たりして条件に合致していれば表示っていうものだと思うけど、ポイントはその総当たりするパターンの絞り込み方にあるんだと思われる。 特に 9 行目以降の limit を決めてるところと、26 行目の next のあたり。

とりあえず、基数が 5 より小さいときに上限 (limit) が 5 というのは shinh さんによれば『適当』らしいので、まあそんなもんかという感じだが、残りの適当じゃない方。

_a の num が 1 以下の場合に使われる 99 は単なるデフォルト値だね、実際はその後の [_a, _b].min でほぼ確実に _b が選ばれるから、実質的には使われることのない数値かと。

1 とか 0 とかはまぁそれなりに。

というのが、まあそういうことなんでしょう。 で、

4 とかは今までに来た数プラス 1 個以上入ることはありえなさげ。 3 は今まで来た数プラス 2 で 2 はプラス 3 まで。

というのが、14 行目の部分を指してるんだと思うけど、こういう見通しっていうのはどうすると頭に浮かぶもんなんでしょうね。 才能なのか経験なのか。 ともあれ、この部分のおかげでかなりのパターン数が省かれて、結果速くなっているんだと思われる。

26 行目も結構効いているのかも知れず。 これは要するに今調べようとしているパターンより実際の数が多くなってる場合は、今後何をしようとパターンが条件に合致することは無いので、そこで検査を打ちきるよということ。 next が呼ばれるところの回数を調べてみたら、base=16 で 1,366 回とかだった。 もしここで next が呼ばれないと、その何倍もの再帰呼び出しがあるはずだから、結構でかい感じ。

そんなこんなで、見た目の怪しさ (失礼) に比べて大変完成度が高く、素直に尊敬の念を抱くほかない次第。 ほんとすごいと思います。

% [OCaml][DouKaku] RFC 4180対応版 CSVレコードの分解

OCaml で Genlex を使って投稿した。→ #4394

とりあえず、サンプルデータは処理できますが…… 程度の手抜き実装。 Gexlex 使ってみたかっただけなんです、すんません。

最初は ocamlyacc と ocamllex を使って書いてたんだけど、途中でめんどくさくなってやめた。 でも、.mly とか .mll とかのファイルも、ocamlbuild が一発で処理してくれるようになってるのがステキすぎて鼻血出そうだったよ。

% [雑談][DouKaku] わしにとってはゴルフよりどう書く?の方が気が楽な感じ

どうしてそう思うんだろう?と考えるに……

  • ゴルフには『短さ』という明確な勝敗基準がある
  • どう書く?には明確な勝敗基準がない

たぶん、これが一番の違い。 ゴルフの場合、いちいち自分のイケてなさを痛感させられるというか、まあそんな感じ。 どう書く?では、もっと自己満足的なところで勝負ができる (勝負している気になれる) というのが、わしには合ってるんじゃないかと。

あと、投稿時にコメントも書けるので、(たとえ誰も聞いちゃいないとしても) 言い訳をぐだぐだ書いておけるところなんかも精神的に楽になれる部分なんじゃないかって気がする(苦笑

まあ、さすがに本題と関係無いことをぐだぐだ書きすぎてもアレなので、そういうのはこっちに書くようにしてるけども。


2007-11-27 [長年日記]

% [雑談] 調子が出ない……

どうにもこうにも調子が出ない。何をやっても思うように進まない。 仕方ないので気分転換に DouKaku? に手を染めてみたりするが、なんだか時間的比率が気分転換の域を越えつつあるような気がしてダメすぎる。

明日こそは、明日こそはがんばろう。(典型的なダメ人間の発言です)

% [clip][Ruby] String#to_proc (raganwald '07)

via Matzにっき.

つい数日前に全く同じネタ (ただし Erlang) を見たばかりだなーと思ったんだが、そっちのページ (Erlang String Lambdas) をよく読むとこのエントリへのリンクが貼ってあった。 そもそもの元ネタは Functional Javascript らしい。 よく考えると、これもなんとなく見覚えがある。

おもしろいことはおもしろいんだけど、やっぱりどうしても黒魔術臭を感じてしまって微妙な感じはするよね。 eval ってのはごく限られた範囲でちょっとずつ使うもんであって、こんな大々的に使うのはなんかちょっと違うんではないかという感情がある。 まあごくごく個人的なものだけど。

なもんで、もしうっかり間違ってこれが Ruby に組み込まれたとしても、わしはあんまり使わない気がするなあ。

本日のツッコミ(全4件) [ツッコミを入れる]

Before...

% jijixi [わかってはいるんですけどね〜(苦笑 まあ、日記にグチってるうちは、わりと余裕あるんだと思います。 本格的に煮詰まって..]

% あろは [大丈夫,煮詰まるはポジティブな言葉ですよ〜 w # 完成が近づいてきたら,たぶんそれどころではなくなるという意味で..]

% jijixi [だがしかし、その煮詰めているものがはたしてそうすべきものなのか否かはわからないのであります(笑 煮詰めるべきでない何..]


2007-11-28 [長年日記]

% [clip] sm1506603 (忙しい人のための 「たたかえ!キャシャーン」(Full Ver.))

某所より。

原曲知ってる人は、おそらく秒殺。 編集のうまさもさることながら、そもそもこんなもんを作ろうと考えるセンスに嫉妬。

% [雑談][FreeBSD] そろそろ 6.3-Release も近いようだが

今使ってる FreeBSD 機のスペックをもう少しグレードアップしたいなぁと思っている。 どっかで手頃なの探してくるかな。 それとも Windows 機を新しくして、今のマシンを FreeBSD に入れ替えるか。 まあ、どっちにしても大して予算は都合できないんで、せいぜい 5 万程度で何とか… といったところだが。

もう少し金があれば、MacBook 買って Parallels (もしくはその類い) って展開もアリなんだけどなー。

% [Python][Ruby] エラーでなくワーニング

Ruby ならわりと普通にできると思ふ。

irb(main):001:0> h = {}
=> {}
irb(main):002:0> h[1]
=> nil
irb(main):003:0> class Hash
irb(main):004:1>   alias __orig_get :[]
irb(main):005:1>   def [](k)
irb(main):006:2>     begin
irb(main):007:3*       self.fetch(k)
irb(main):008:3>     rescue
irb(main):009:3>       print "key not found\n"
irb(main):010:3>       nil
irb(main):011:3>     end
irb(main):012:2>   end
irb(main):013:1> end
=> nil
irb(main):014:0> h[1]
key not found
key not found
key not found
key not found
key not found
key not found
=> nil

最後にメッセージがたくさん出てるのは irb が Hash#[] を使ってるせいなはずなんで、気にしない方向で。

Python でも dict.__getitem__ を上書きすればできそうな気がしたけど、組み込みクラスに setattr するのはちょっときびしいみたいなので、dict のサブクラスを作るとかしないとダメかも。

In [1]: class MyDict(dict):
   ...:     __orig_getitem__ = dict.__getitem__
   ...:     def __init__(self, d={}):
   ...:         dict.__init__(self, d)
   ...:         return
   ...:     def __getitem__(self, key):
   ...:         try:
   ...:             return self.__orig_getitem__(key)
   ...:         except:
   ...:             print 'key not found'
   ...:             return None
   ...: 
In [2]: d = MyDict({1:'foo'})
In [3]: d[0]
key not found
In [4]: d[0] = 1
In [5]: d[0]
Out[5]: 1

Python も組み込みクラス以外なら結構無茶が効くんだけど、組み込みだといろいろ制限あるみたいね。 まあ、その分最適化されてて速いのかなという気はするが。

% [雑談][Rails] 初心者を惑わす render :action が憎い

Rails を使い始めた頃に悔しい思いをしたのを思い出したので書いとく。

ActionController::Base#render ってね、引数によって色々な動きをするわけね、それで、最初に render :action => 'hoge' という書き方を知ったときには、当然のように『hoge というアクション (メソッド) を実行してくれるんだな』と思ったわけよ。 思うでしょ、思うよね? だって、パブリックメソッドとアクションは対になってるんだから、action と名が付けばそうなんだろうと思ってもしかたがないと思うんだ。 わし英語読めないし(の

でもそれは大いなる勘違い。

実際にソースを追ってみるとわかるけど、render :action => 'hoge' って、実質、render :template => "#{self.controller_name}/hoge" って書くのとほぼ同義なわけね。 要するに、自分用のディレクトリに入ってる 'hoge.*' という名前のファイルをレンダリングしますよってだけの話で、実際のところアクションなんてほとんどまったく関係無い。 で、やってみるとわかると思うけど、hoge というアクションが存在しなくても hoge.rhtml とかってファイルが存在すれば何事もなく処理される。

結局のところ、あるアクションから別のアクションをフィルターなんかも含めて綺麗に実行する方法は無い…… と思う。 アクションに対応したメソッドを呼ぶだけじゃ、フィルターは実行されないし。 でもさー、あるんじゃない? リダイレクトじゃなく直接別のアクションを実行したいときが。 それとも、それって設計が悪いの?

まあ少なくとも、そういうのを期待するのは、現状の Rails に対してあまり相性の良くない作りなんだろうとは思う。 だから、相性が良くなるようにアプリケーションを作り直すのも良いだろう。 でも、render :action って名前だけは何とかしてもらえんかな。 どう考えても名前負けしてるっていうか、render :action_name とかの方が良いんじゃないかと思うんだが、どうさ。

% [clip][game] sm1538794 (スーパーストリートファイターII ザンギエフでTool-Assistしてみた)

究極のザンギさん。 DJ の大足とかバイソンの大パンの出掛かりを吸うなんつー、ごく稀にやられるだけで泣ける技を連発するザンギさん非道。

だが、にっくきガイルが『待ち』でやられてるのは痛快だった(笑

本日のツッコミ(全2件) [ツッコミを入れる]

% きむら(K) [「わーにんぐ」とか書いていると某氏のチェックが入ったりして :)]

% jijixi [えー?(苦笑 でも、わしが書いたわけじゃないですし(汗]


2007-11-29 [長年日記]

% [Ruby][Python] エラーでなくワーニング (2) (プログラミング日記)

あ、なるほど、クラスを変更しちゃダメなのね。 じゃあ、こうです。

irb(main):001:0> h = {}
=> {}
irb(main):002:0> h[1]
=> nil
irb(main):003:0> class << h
irb(main):004:1>   def [](k)
irb(main):005:2>     begin
irb(main):006:3*       self.fetch(k)
irb(main):007:3>     rescue
irb(main):008:3>       print "key not found\n"
irb(main):009:3>     end
irb(main):010:2>   end
irb(main):011:1> end
=> nil
irb(main):012:0> h[1]
key not found
=> nil

特異メソッド万歳。

% [Python][Ruby] Delegator

morchin さんの一連の話を見ていて、ふと思ったのが「Ruby の Delegator みたいなのって Python には無いのかな」ということだったんだけど、ちょっとマニュアルを見たかぎりでは無いっぽい。 ので、試しに軽くインチキ実装してみた。

% cat delegator.py
class Delegator:
    def __init__(self, obj):
        self._self = obj
        klass = obj.__class__
        methods = set(dir(obj)) - set(dir(self))
        methods.discard('__class__')
        for m in methods:
            setattr(self, m, getattr(obj, m))

class MyDict(Delegator):
    def __getitem__(self, key):
        if key not in self._self:
            print 'key not found'
        else:
            return self._self[key]
In [1]: import delegator
In [2]: d = delegator.MyDict({})
In [3]: d[0]
key not found
In [4]: d[1] = 1
In [5]: d[1]
Out[5]: 1
In [6]: list(d)
Out[6]: [1]
In [7]: len(d)
Out[7]: 1

まあ、細かいことはあまり考えてない手抜き実装なんで、使いものになるかは微妙だけど、例の話のようなシチュエーションなら、こういう Delegator みたいなクラスがあらかじめ用意されてれば、わりと簡単にインスタンスを拡張できて便利かな、とか。

ちなみに、

RubyはPythonの非結合メソッドを利用するdict.__getitem__(self, key)みたいなことはできないのだろうか?

という話ですが、そのままずばりの方法は無理ですね。 任意のクラスのインスタンスメソッドを、インスタンス化せずに取得する方法は無いはずです。 (追記: UnboundMethod というものがあるそうで (コメント欄参照)、これを使えばできそう。 なんとなく効率悪そうな気はするけど)。 でもオーバーライドしている親クラスの元のメソッドは super で呼べるので、

irb(main):001:0> class MyHash < Hash
irb(main):002:1>   def [](key)
irb(main):003:2>     if self.has_key?(key)
irb(main):004:3>       super(key)
irb(main):005:3>     else
irb(main):006:3*       puts 'key not found'
irb(main):007:3>     end
irb(main):008:2>   end
irb(main):009:1> end
=> nil
irb(main):010:0> h = MyHash.new
=> {}
irb(main):011:0> h[0]
key not found
=> nil
irb(main):012:0> h[0] = 1
=> 1
irb(main):013:0> h[0]
=> 1

こういうのは書けます。

% [雑談] ビールの泡がキレイに出せるグラスとか

そういうのが欲しい。

ギネスドラフトのようにビール側で仕掛けがしてあるものもあるけど (フローティングウィジェットを考えた人は神だね)、大多数のビールはそうではないわけで、なんかこう、あんまり神経使ってテクニックを駆使しなくてもキレイに泡が出るグラスとか欲しくなるわけさ。

なんとなく底の部分の形状を工夫すれば何かできそうな気がするんだよね。 なんつーかこう、流体力学的にさ、斜めにしてビールを流し込むとうまい具合に底の方で渦ができて細かい泡ができるとか、そういうの。

実はすでにどっかにあるんじゃないの?って気もするんだけど、どなたかご存知ない?

本日のツッコミ(全9件) [ツッコミを入れる]

Before...

% jijixi [ふむふむ。 しかし着物屋か…縁が無さすぎる(苦笑]

% znz [Hash.instance_method("[]")とかHash.instance_method(:[])とかでUn..]

% jijixi [UnboundMethod なんていうクラスがあったんですね。 知りませんでした。 これなら確かにできそうな感じです..]


2007-11-30 [長年日記]

% [clip] 布教しようと頑張ってたのに (育児板拾い読み@2ch)

微笑ましすぎるけど、神父さん大丈夫なのか(苦笑

神主さんが教会のイベントに参加するのはアリかもしれないけど (多神教だしな)、神父さんが神社の行事に参加するのはヤバい気がするんだが、日本に宗教戦争はありませんってことで FA?

あとまあ、なんだ、一言言わせてもらえれば、破魔矢も十分違和感ありすぎるから(笑

本日のツッコミ(全3件) [ツッコミを入れる]

% きむら(K) [さすがに30年もかけて戦争するようなことはありませんでしたが、 宗派間のいざこざはなかったわけではないです。 #異な..]

% じょり [キリスト教も、土着の宗教の影響を受けたことはけっこうあるので(ロシアのギリシア正教なんかがその典型)、別に珍しくない..]

% jijixi [同じサイトにイスラムなネタもあったので貼っときますね。 http://ikuzi2.blog73.fc2.com/..]


トップ 最新 追記

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com