上諏訪
上諏訪
上諏訪
mwantenna は更新検出が早いそうで、素晴らしいことです。 五月雨は exponential backoff でアクセス間隔を伸ばしていくので、 5分間隔でアクセスする mwantenna よりも更新検出が遅れることが多いのはまずまちがいないでしょう。
また、そういうアンテナの LIRS を五月雨で参照すれば、 五月雨自身で頻繁にアクセスしなくても更新をタイムリーに検出できるので、 私としてはどちらかというと五月雨よりは mwantenna (もしくは他のアンテナでもいいので 5分間隔で更新を検査する cron の設定) に普及して欲しいように思います。
さて、五月雨で更新を素早く検出するには、他のアンテナからなるべく たくさん LIRS をとってくるのがコツである。 少なくともいろんなアンテナに監視されている連中については。
% cat `ls tmp/*.lirs|uniq -t_ -W1`|awk -F, '{ print $6 }'|sort|uniq -c|sort -n|tail 14 http://www.daionet.gr.jp/~knok/diary/ 15 http://triaez.kaisei.org/~kaoru/diary/ 15 http://www.unixuser.org/~ysjj/diary/ 16 http://www.mhatta.org/diary/ 16 http://www.topstudio.co.jp/~kmuto/d/ 17 http://cvs.m17n.org/~akr/diary/ 17 http://diary.imou.to/~AoiMoe/ 17 http://kitaj.no-ip.com/tdiary/ 22 http://www.rubyist.net/~matz/ 23 http://namazu.org/~satoru/diary/
この一番多いひとをどのアンテナが監視しているかというと、
% grep -l http://namazu.org/\~satoru/diary/ `ls tmp/*.lirs|tac|uniq -t_ -W1` tmp/af-znz.jin.gr.jp-sites_03-05_12:18.lirs tmp/af-www14.cds.ne.jp-nantenna_03-05_12:20.lirs tmp/af-www.yui.gr.jp-natsumican_03-05_13:00.lirs tmp/af-www.topstudio.co.jp-natsumican_03-05_13:10.lirs tmp/af-www.tdiary.net-tdiary_03-05_13:10.lirs tmp/af-www.shudo.net-natsumican_03-05_13:02.lirs tmp/af-www.nijino.com-natsumican_03-05_13:00.lirs tmp/af-www.mhatta.org-natsumican_03-05_13:00.lirs tmp/af-www.kimuchi.org-fm_03-05_12:50.lirs tmp/af-www.hikita.org-natsumican_03-05_12:44.lirs tmp/af-web.sfc.keio.ac.jp-sites_03-05_12:16.lirs tmp/af-sugi.nemui.org-sites_02-27_11:18.lirs tmp/af-pure.fan.gr.jp-latest_03-05_12:56.lirs tmp/af-moonrock.jp-ruby_03-05_12:40.lirs tmp/af-marimo.deisui.org-fm_03-05_12:16.lirs tmp/af-ko.meadowy.net-sites_03-05_12:37.lirs tmp/af-kitaj.no-ip.com-sites_03-05_12:56.lirs tmp/af-furukawa.ch.kagu.tus.ac.jp-sites_03-05_12:20.lirs tmp/af-devlog.moonwolf.com-sites_03-05_13:10.lirs tmp/af-ayame.tkym.org-sites_03-05_12:58.lirs tmp/af-arika.org-sites_03-05_12:54.lirs tmp/af-a.northeye.net-natsumican_03-05_12:18.lirs tmp/af-a.hatena.ne.jp-source_03-05_13:12.lirs
というわけで、それぞれのアンテナの更新間隔を調べると、だいたい、
znz.jin.gr.jp 毎時50分 www14.cds.ne.jp 毎時20分 www.yui.gr.jp 毎時00分 www.topstudio.co.jp 毎時00,10,20,30,40,50分 www.tdiary.net 毎時00,10,20,30,40,50分 www.shudo.net 毎時23,53分 www.nijino.com 毎時55分 www.mhatta.org 毎時00,30分 www.kimuchi.org 毎時20,50分 www.hikita.org 毎時14,44分 web.sfc.keio.ac.jp 毎時16分 sugi.nemui.org 毎時50分 pure.fan.gr.jp 毎時26,56分 moonrock.jp 毎時36分 marimo.deisui.org 毎時11分 ko.meadowy.net 偶数時32分 kitaj.no-ip.com 毎時56分 furukawa.ch.kagu.tus.ac.jp 毎時15分 devlog.moonwolf.com 毎時00,05,10,15,20,25,30,35,40,45,50,55分 ayame.tkym.org 00,03,06,09,12,15,15,18,21時00分 arika.org 毎時13,33,53分 a.northeye.net 毎時18分 a.hatena.ne.jp 不定?
という感じである。
というわけで、1時間毎よりも高頻度で動くアンテナで、
00 00 00 00 00 05 10 10 10 11 13 14 15 15 16 18 20 20 20 20 20 23 25 26 30 30 30 30 33 35 36 40 40 40 44 45 50 50 50 50 50 50 53 53 55 55 56 56
というくらいの更新検出が行われている。 ただ、これらのアンテナの中には毎回はアクセスしないもの (五月雨はそうだし他のアンテナでもそういう挙動をするものがある) があるので、実際にはもう少し減る。
ともあれ、五月雨は定期的に更新される対象に関してはその更新のタイミングを 見計らって取りにいけるので、 普通のアンテナの LIRS は更新されるときに取りにいける。 それで、LIRS の中身を見て興味のあるページが更新されていたら 実際に確かめて更新を検出する、というわけである。 というわけで、LIRS をたくさん使えばそれなりに素早く検出できたりするのである。 いろんなアンテナに監視されている連中に限っていえば、だけど。
% google-count {中国,支那,シナ}の百科事典 35 中国の百科事典 4 支那の百科事典 5 シナの百科事典
あるオブジェクト内部にフラグ x があり、それを外部から設定するインターフェースを設計するとしよう。
まず思いつくのは
obj.x = true obj.x = false
である。
さて、べつに上記の方法が悪いわけではないが、他の方法も考えられる。 たとえば、
obj.toggle_x
というようにフラグを反転させる(トグルする)というのがある。
elisp ではトグルをよく見かける。 ただし、トグルは人間用であって、プログラムは使うべきでないとされている。
さて、プログラムにはトグルはなぜ良くないのだろう?
たぶん、 フラグを反転したいケースよりもフラグを直接設定したいケースのほうが多いから、 というのがあるのだろうが、なぜそうなのだろう?
% google-count api-usability 279 api-usability
Lambda the Ultimate: Evaluating API usability at Microsoft
ひっかかったので読んでみる。 なかなか面白い。
ThinkPad X31 以降の DtoD は Phoenix FirstWare Recover というのを使っているのか。
ある attr だけ書き出したくない場合、 marshal_dump でそれ以外の全てをまとめて返せばいいわけですが、 「それ以外の全て」を指定するのが面倒な場合、
class C def attr class << self class << self self end end.instance_variable_get(:@attr) end def attr=(val) class << self class << self self end end.instance_variable_set(:@attr, val) end end c = C.new c.attr = 1 p c.attr d = Marshal.load(Marshal.dump(c)) p d.attr
というように attr を定義することにより、 dump されない属性を定義することも出来ます。
いや、べつにこういう書き方を勧めているわけではありませんよ?
3月に入ってから、五月雨は core を吐かないし、 undefined method `queue' というのも出ない。 すこぶる快調である。
先月の末に Hash に手が入ってバグが直った結果、 快調になったということが期待されるのだが、 これは本当にバグが直ったということを意味するのだろうか?
最近 10日間、先月までと同様に五月雨を動かしていたにもかかわらず トラブルが起きていないという事実を、 システムの信頼性というページを眺めつつ、考えてみる。
undefined method `queue' というのは 以前まとめたように 2003-07-08T11:45:53 から 2004-02-26T15:18:20 までに 69回発生している。 ということは、
% irb -r time irb(main):001:0> l=68/((Time.parse("2004-02-26T15:18:20") - Time.parse("2003-07-08T11:45:53")) / (24*3600)) => 0.291660815032923
というように、故障率λ≒0.3回/日 ということになる。
これが 10日間故障しない確率は、
irb(main):002:0> Math.exp(-l*10) => 0.0541169328548749
というわけで、約5% しかない。
ところが現実には故障していない。 つまりバグが直っている確率は 95% くらいということか?
5% ならたまにはそんなこともあるかもしれないと感じなくもない。
では、0.1% になるにはあと何日必要か?
irb(main):005:0> -Math.log(0.001)/l => 23.6842075552809
24日ということは、(すでに 10日経ってるから) あと 2週間くらいか。
勧めないなら使いやすくなくてもいいんじゃないかと思いつつ書いてしまった。
% ruby -e ' class Module private def volatile_attr_accessor(name) vname = "@#{name}" define_method(name) { class << self class << self self end end.instance_variable_get vname } define_method("#{name}=") {|v| class << self class << self self end end.instance_variable_set vname, v } end end class C volatile_attr_accessor :attr end c = C.new c.attr = 1 p c.attr d = Marshal.load(Marshal.dump(c)) p d.attr ' 1 nil
「まぐろ丼や」という店がある。
感想: google で探すのが難しい。
高解像度なもの
xmlmine というプログラムを公開した。
知っている人は知っている FREQT というアルゴリズムを使ったデータマイニングツールで、
% cat sample.xml <a> <a> <b/> <a> <b/> <a/> <b/> </a> </a> <a> <a/> <b/> </a> <b/> </a>
というような XML ファイルがあったとすると、 次のようにしてデータマイニングできる。
% ./xmlmine.sh sample.xml patternset-0 rootocc:4 maxsize:2 [ a a ] /sample.xml/a /sample.xml/a/a[1] /sample.xml/a/a[1]/a /sample.xml/a/a[2] ...中略... patternset-5 rootocc:2 maxsize:4 [ a a a b ] /sample.xml/a /sample.xml/a/a[1] FREQT finished. 6 patternsets reported. (0.271s)
うぅむ。求まったパターンので木構造をインデントで表現しているのだが、 あまり木のように見えないな。
DELL のでっかいノートが来る。
電源を入れると、EULA を読めと出て来るので、 箱の中を探し回ったのだが見つからない。
しょうがなくて電話したら、ついてないのでそのまますすめとのこと。 うぅむ。
「読まずにいられなかった 2冊」が何かと問われる。
ひとつは「ハイウイング・ストロール」と答えられたのだが、 もうひとつが思い出せなかった。 帰ってから確認してみると「彩雲国物語 黄金の約束」であった。
しかし、その 2冊以降でも「吉永さん家のガーゴイル2」が それらに近い感覚だったし、 「我が家のお稲荷様。」「先輩とぼく」も続きが出れば そういう感覚になりそうな気がするわけで、 こう見直してみるとけっこう頻繁にそういう感覚になっているなぁ。
Regexp のキャプチャの構文についてですが、 具体的な構文は言及されなかったと思います。
私としては、named group の記法を利用するのはどうだろうかと思っていて、 次のような感じです。
if /xxx(?<foo>....)xxx(?<bar>....)/ =~ str p foo # マッチすると代入されている p bar end
また、これも読書会では言わなかった気がしますが、 おそらく、$1 よりも長くなる記法は受け入れられないと思います。
if /xxx(...)xxx(...)/ =~ str foo = $1 bar = $2 p foo p bar end
というのに比べて、
if /xxx(?<foo>....)xxx(?<bar>....)/ =~ str p foo # マッチすると代入されている p bar end
というのは(少しですが)短いため、 ユーザは自然とこちらの形式に移行する可能性があります。 そして、もし自然な移行が起きるのであれば、 $1 に警告をつけて追い出すのも現実的になるかも知れないと思っています。
しかし、
if m = /xxx(?k=foo:....)xxx(?k=bar:....)/.match(str) foo, bar = *m.select(:foo, :bar) p foo p bar end
とか
if /xxx(?k=foo:....)xxx(?k=bar:....)/.match(str, binding()) p foo p bar end
というようなの記法は $1 を使う形式よりも長いため自然な移行は起こらず、 $1 とかに警告をつけてユーザを追い出すのは、 あまりにたくさん文句が出て非現実的なのではないかと感じます。
しかし、警告というのは地上げに似ている。
「利点があるんだから長くなってもいい」わけではありません。
短いけれど順番の変化に弱い書き方と、 長いけれど順番の変化に強い書き方がある場合、 プログラマはどちらの書き方を選ぶかで短さと順番の変化に対する強さの どちらか「だけ」を選ばなければなりません。
この選択のどちらが適切かは状況によって異なります。 one-liner なら短さを選ぶでしょうし、 頻繁に順番が変わるならその変化に強い書き方を選ぶでしょう。 しかし、ひとつのコードに対してもこの状況は変わるものです。 最初は簡単に書ける短いほうを選んだとしても、 後から順番が変わって面倒臭い作業(番号を振り直すか、名前を使うように変える)を するはめになることは十分に考えられます。
ここで、もし両方の利点を持つ書き方があれば、 この面倒臭い作業の発生を避けることができます。 つまり、短くて順番の変化に強い書き方があれば、 プログラマはどちらかの利点を選択する必要がなく、 つねにひとつの書き方をすれば両方の利点を得られます。 また、これはスタイルを統一する方向に誘導するという意味でもいいことです。
理想は、いちばん短い書き方がいちばん良い書き方であることです。 もちろん、それが常に可能なわけではありませんが、 それが可能な場合には追求すべきだと考えています。 したがって「利点があるんだから長くなってもいい」という考え方には強く反対します。
さて、「メソッドを呼ぶと知らないうちにローカル変数に代入されてる」のが想像しにくい、というほうは考慮の余地があります。 実際、知らないうちに代入されるのを避けるために #{} で展開した中では ローカル変数へは代入しないと制約したわけです。 この制約のため、ローカル変数への代入はそのローカル変数の名前を書いたところにしか起こりません。 したがって、これはブロックと似ています。 (Regexp がクロージャだと考えればブロックと似ているのは当り前ですが)
meth { a = 1 }
と記述した場合、meth を呼ぶと meth が yield するときには a に代入されるわけですが、 これをもって知らないうちに代入されているという人はあまりいません。
したがって、/(?<a>...)/ に対するマッチで a に対する代入が起こるのが想像しにくいとしたら、 それはこれが通常の代入の構文と似ていないという理由しか思い当たりません。
とすれば、構文を代入に似せることによって代入が起こることが想像しやすいようにできる可能性があります。 例えば、Perl6 の記法では普通の代入の構文を使うので想像しやすいでしょう。
また、Perl6 のような drastic な変更をしないとすれば、とりあえず = という記号を使うということが考えられます。 /(?<a=>...)/ とかするのはどうでしょうね。
Groovy を試す。
1> x = [] 2> t = "x = ${x}" 3> println t 4> go x = [] 1> x << 1 2> println t 3> go x = [1]
なるほど。
メソッド呼び出しで、というのは [ruby-dev:20689] で小迫さんが触れてますね。 実装は method_missing を想定しているようですが。
それはそれとして、 まず「他のメソッド内でローカル変数に代入させるという操作」といいますが、 Regexp がクロージャであると解釈すれば、 代入しているのは他のメソッドではなく、 そのメソッドの中のコードであると解釈できます。 このように解釈できるのは lexical scope なためであり、 lexical scope にこだわっているのは他のメソッド内で任意のローカル変数に代入されることを防ぐためで、 他のメソッド内でローカル変数に代入させることの危険性は十分に分かった上でデザインしているつもりです。
あと「Ruby 的でない」からだめ、というのはこの場合あまり説得力が感じられません。 まぁ、まつもとさんとかもそういう言い方をすることがある (例: RCR229) わけですが、 まつもとさんがそういう言い方をするケースに比べるとこれはかなり小さい変更で、 Ruby を Ruby でなくしてしまうほどではないように思います。 もちろん、あおきさんの Ruby 的という感覚から外れるのはそうなんでしょうが、 私の感覚がそれに一致するとは限らないわけで、具体的な欠点を述べると説得力が出ると思います。 もし、そういう言葉では述べられない感覚について述べているのであれば... それでもやっぱり言葉にしないと議論できないのでがんばって言葉にしてくださいとしかいえませんけど。
「正規表現を複数のパーツに分割したり定数に入れたりするのをやめてしまう」可能性はあるかもしれません。 それを解決するには、yacc みたいに、個々のパーツごとに action を書けるのがいいかもしれません。 クロージャだと考えれば、任意のコードが実行できてもいいですよね。
そういえば、昨日読んだときは、まつもとさんを説得できないだろうとか書いてあった気がする...
ふむ。五月雨での保存期間を伸ばそう。
http://i.loveruby.net/d/20040326.html#p01
現在の Ruby でクロージャを作る構文から外れるのは事実です。 それを解決するとすると、例えば /...(?{a=}...).../ というように {} を使うのはどうでしょうね。 いっそ /...(?{|a|}...).../ とか? いや、これはブロックローカルになる構文だからまずいか。
また、スコープに関しては、 Ruby2 では普通のクロージャについてもそういうスコープになる見込みが高いわけで、 Ruby 的にはそういうのも有り得るのでしょう。
アクションについては... 強力な記法を導入したとして、 一番簡単なケースにおける記述量をいかに抑えられるか、 というところがデザイン上の問題ですかね。 強力な記法は長くなりがちなのですが、 最初の目標は $1 よりも短い(そして良い)記法を導入するというところにあって、 その目標を達成できなければ本末転倒なので。
思ったのだが、議論に勝てる仕様が良い仕様とは限らないよなぁ。
すくなくとも、相手の要求をどんどん受け入れていくというのは仕様が膨らんで危険で、そしてクロージャというのはなんでも受け入れられるし。
委員会言語の問題というのはそういうところにあるのかもしれない。
やはり、他の人の要求は自分自身で気に入ったもの以外ことごとく reject して、 自分が一番頻繁に使うところに最適化した最小の記法を提案したほうがいいのかも。
いや、委員会言語的な問題を避けつつ議論をする方法を考えるほうが建設的か?
でも、それが難しいから委員会言語なんて話になるのではないだろうか。
うぅむ。今月の「少年魔法士」ならぬ「あんまり少年じゃない人もいる魔法士」は、 なんというか、妙にツボにはまってしまった。
コーセルテルはゼロサム行きか。
% google-count read_partial read_available read_buffered read_buffer read_chunk read_block 0 read_partial 0 read_available 0 read_buffered 0 read_buffer 0 read_chunk 0 read_block
え? あぁ、微妙に形式が変わったのか。
まぁ、HTML から取り出す限り許容すべきトラブルだな。 直しておく。
% google-count read_partial read_available read_buffered read_buffer read_chunk read_block 80 read_partial 279 read_available 138 read_buffered 3940 read_buffer 517 read_chunk 1560 read_block
テンプレートの API をやっと決めて、ちょっと実装する。
とりあえず rss2html を試しに実装してみる。
#!/usr/bin/env ruby require 'htree' RSS = '{http://purl.org/rss/1.0/}' DC = '{http://purl.org/dc/elements/1.1/}' rss = HTree.parse(ARGF.read) HTree.expand_template{<<'End'} <?xml version="1.0"?> <html> <head> <title _text="rss.title">dummy title</title> </head> <body> <h1><a _attr_href='rss.find_element("#{RSS}link").extract_text' _text="rss.title">dummy title</a></h1> <dl _iter_children='rss.traverse_element("#{RSS}item")//item'> <dt _text='item.find_element("#{DC}date").extract_text' >dummy-date</dt> <dt><a _attr_href='item.find_element("#{RSS}link").extract_text' _text='item.find_element("#{RSS}title").extract_text' >dummy title</a></dt> <dd _text='item.find_element("#{RSS}description").extract_text' >dummy description</dd> </dl> <hr/> <p>generated by rss2html</p> </body> </html> End
うぅむ。 traverse 系のメソッドが甘いのは以前からの懸案だからいいとして、 入力側の encoding の扱いも甘いな。 mconv も htree に移して、auto-detection を組み込むべきか。
% ruby -I. -rhtree <<'EE' uri = "http://xxx" pp HTree{'<a _attr_href=uri>yyy</a>'} EE #<HTree::Doc {elem <{http://www.w3.org/1999/xhtml}a href="http://xxx" xmlns="http://www.w3.org/1999/xhtml"> {text "yyy"} </a>}>
なんて出来たりして、外側のローカル変数がへーきで見えるのがなんとも非常識。
いや、eval 内のローカル変数の仕様は変わるという話を聞いたような...
「eval内で新規に登場したローカル変数はeval終了後消える」か。 新規じゃないから問題ない、だろう。たぶん。
うぅむ。もしかして POSIX は 2001 から閏秒を許容する?
英語をちゃんと解釈できたという自信がいまひとつ持てないのだが。
[latest]