Page 1/16: 1 2 3 4 5 6 7 8 9 »

2008-10-29

近況

観光目的で7ヶ月ほど京都旅行に行っていた。
祇園祭楽しかったですね。

2008-02-18

2008-02-08

オープンソース版のFastladderが公開されました

まだまだバグとか色々残ってるかとは思いますが、リリースされました。
http://fastladder.org/
http://blog.livedoor.jp/staff_reader/archives/51181618.html

ニュース記事
http://www.itmedia.co.jp/news/articles/0802/07/news032.html
http://internet.watch.impress.co.jp/cda/news/2008/02/07/18390.html
http://itpro.nikkeibp.co.jp/article/NEWS/20080207/293305/

元々Railsで動いてたわけではなくて、個人でもインストールしやすいようにコンパクトに書き直したものです。
稼働してるサービスは、他のライブドアのサービスと同様に(良く知られている通り)mod_perlとSledgeで動いてます。

以前からHTMLやJavaScriptのソースは自由に見ることが出来ましたが、ライセンス不明瞭で使って良いのかどうかよく分からないという問題がありました。オープンソース化にあたって、MITライセンスということになります。Railsのバックエンドは主に上田君がやってくれました。僕も結構書いてます。Rubyを採用したのはネタというわけではなく、マルチプラットフォームで動かすのが比較的楽なのと、初心者にも分かりやすいとかそんな理由です。

そんなわけで、ライブドアを退職することになりました。
まだ退職日前ですが、2月1日から有給をもらってます。

会社は辞めますがオープンソース版のコミット権限は持っているので、マイペースで開発に参加していきたいと思ってます。
JavaScriptのソースは殆どそのまんまなので、少し整理して開発に参加しやすい状態にしようと思ってます。

今後のことは追ってお知らせします。転職先は既に決まっているので月収1000万以上出せる場合のみ連絡ください。

というわけで今後ともよろしくお願いします。

2008-01-04

あけましておめでとうございます

今年もよろしくお願いします。


2007-11-27

JavaScriptにおけるdeep clone

http://blog.livedoor.jp/dankogai/archives/50957890.html

まず、Object.prototypeにメソッドを生やしてしまうとfor inでキーを列挙するときにいちいちhasOwnPropertyを使わないといけなくなるので普通は使いません。影響が大きすぎるので、よっぽど変態的なライブラリじゃないと使わない。他のライブラリと組み合わせるとほぼ確実に問題が起きる。それから、deep_cloneが欲しい場合はJSONを作ってevalすればよい。パフォーマンスを気にする場合とか、浅いコピーが必要な場合はそれなりに工夫する必要があるけど。

で、JSONにするのにFirefoxだとtoSourceというのが使える。unevalというラッパーがあって、これだとnullでも平気。
http://subtech.g.hatena.ne.jp/cho45/20071125/1195964965

つまりFirefoxだったらeval(uneval(obj))でOK。
Object.deep_clone = function(obj){
    return (typeof uneval == "function") ? eval(uneval(obj)) : eval(Object.toJSON(obj));
}
// Object.toJSONは別途適当に実装。prototype.jsに入ってたりしますね。


見てのとおり、一つ嫌な問題があって、prototypeに割り当てているにも関わらず、for (k in object)でclone自身が見えてしまうのです。これって何とかならないのかなあ....__proto__プロパティを使う方法だと新しすぎる?


これはhasOwnPropertyを使う。prototypeチェーンを辿らないで、そのオブジェクト自身のプロパティとして存在している場合のみtrueを返す。
obj = {keyname: "hoge"};
"toString" in obj // true
"hasOwnProperty" in obj // true
obj.hasOwnProperty("keyname") // true
obj.hasOwnProperty("hasOwnProperty") // false


http://blog.livedoor.jp/dankogai/archives/50957994.html

これも同様、Object.prototypeにtoSourceを自前で定義してしまうと影響が大きすぎるので、使えない。

----
突っ込まれそうなところを補足

- 適切にtoSourceが設定されてれば、任意のクラスのオブジェクトでもeval,unevalでcloneを作れる。
- toJSONでtoSourceと同等の出力を期待するのは間違ってる気がするので、クロスブラウザでunevalを実装した方が良いかも。
- okuさんが書いてるけど、元のオブジェクトに影響を与えないで、一部のプロパティのみを書き換えたオブジェクトを作りたい、という要求を満たすにはまさにprototypeを使った継承が使えるので、他の言語と比べてdeep_cloneの必要性自体が薄い、気がする。(元のオブジェクトの変更が反映されちゃうから微妙か)

こんなの。
function clone(obj){
    var F = function(){};
    F.prototype = obj;
    return new F;
}


プリミティブ値を継承した場合に起こる問題を解消してあるのがこれ。
http://nanto.asablo.jp/blog/2006/10/18/566348

2007-11-17

Amazonのギフト券のコピペを楽にするGreasemonkeyスクリプト

500円を6枚とかで送られてもコピペするのが面倒くさいのでグリモン書いた。

http://la.ma.la/misc/userjs/amazon_gift.user.js

2007-09-30

livedoor Readerに偽オフラインモードをつけるGreasemonkeyスクリプト

出先で回線が使えない可能性を考えて作った。
http://la.ma.la/misc/userjs/ldr_fake_offline_mode.user.js

:offlineで実行。:offline 20だと20件読み込み。適当な実装なので同期とかはない。

仕組みはこんな感じ
// 常にキャッシュを使う
Cache.prototype.check_expr = function(){return true};

// 設定変えて再描画
Config.use_autoreload = false;
Config.touch_when = "manual";
Config.view_mode = "flat";
Config.limit_subs = 100;
get_unread.cache.max = 500;

// 再描画
subs.update();

// reload無効化
Control.reload_subs = function(){}

// 全部先読み
Ordered.list.forEach(prefetch);


----
追記

最初にあげたバージョン、非表示状態のフィードも読み込もうとするので未読が多いと上手く動かないのとサーバー負荷が無駄に増える状態になってました。
インストール済みの人は更新をお願いします。

2007-09-27

SiteConfigWikiの情報を使ってはてなスターをくっつけるブックマークレット書いた

頑張って作ろうかと思ったら既にConfigLoaderというのが定義されてたからそれ使うだけで良かった。

Add HatenaStar

JSONをevalしないでクライアントサイドでパースしたほうが安全じゃない?というような話。
http://d.hatena.ne.jp/ku0522/20070927/1190868347

Greasemonkeyみたいに外部ドメインのデータ引っ張ってこれるとは限らないので、JSONPがあること自体は良いことだと思う。JSONPがあるのは設定不要で簡単に貼り付けられるようにするためだと思うけど、動的に取得するようになってるとWikiで挙動を変えられてしまうので危険だと思う。例えばJSONを出力する処理にバグがあった場合とか、凄く処理が重くなるセレクタとかを指定されるとか。あくまでコード生成の補助に使うぐらいがいいんじゃないかなあ、という気がする。

整形済みのソース。HatenaStar.js自体のロード完了を検知するのが面倒くさいのでタイマーで回した。
(function(){
    var l=function(src){
        var s=document.createElement('script');s.charset='utf-8';s.src=src;
        document.getElementsByTagName('head')[0].appendChild(s);
    };
    l("http://s.hatena.ne.jp/js/HatenaStar.js");
    var t = setInterval(function(){
        try{
            Hatena.Star.ConfigLoader.addEventListener('load', function(){
                new Hatena.Star.EntryLoader();
            });
            new Hatena.Star.ConfigLoader();
            clearInterval(t);
        } catch(e){}
    }, 100);
})();

2007-09-18

Mozilla24でしゃべってきました

9/15日にMozilla 24 出張Shibuya.js 24でしゃべってきました。
http://shibuyajs.org/articles/2007/08/24/Shibuya-js-24

資料はこちら。
http://ma.la/files/shibuya.js/mozilla24.html

JavaScriptでBloom filterのデモ。今のところ実用性が無い。仕組みを理解するのには良いかも。
http://la.ma.la/misc/js/bloomfilter/

Bloom Filterについてはここら辺が詳しい。
http://chasen.org/~taku/blog/archives/2006/01/bloom_filter_1.html
http://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AB%E3%83%BC%E3%83%A0%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF
http://dev.ariel-networks.com/modules/xfsection/article.php?articleid=18

以前書いたとおり、livedoor ReaderのFeed Discover APIの中で使っています。存在する可能性が著しく低いキーを大量に問い合わせる場合に有効だと思う。Squidで使われたりしてるみたいですね。

memcachedは存在するデータをキャッシュするのに使えるけれど、ヒットしないことを判別するためにキャッシュを作るようにしてしまうと大量のゴミクエリをキャッシュすることになってしまう。Bloom filterを使うとDBに問い合わせる前にキーが存在するかどうかをオンメモリでチェックすることができます。検索に応用したりもできるみたいで、シグネチャ法という全文検索の手法があります。CPANモジュールのText::Bloomというのがbloom filterを使った実装。古いのであんまり使えないと思うけど。

解説を読むと分かりますが、存在しないキーでもtrueを返す可能性があります。データをコンパクトにできる代わりに、正確じゃなかったりする。そういうアルゴリズムは面白いですね。

CDATAの中に]]>を入れたい場合どうすればいいか

CDATA区域を二つに分けるのが正解。周知のために晒し上げ。
http://lowreal.net/logs/2005/07/07/2.html

例えばRSSフィードを作るときにCDATAを使っていてユーザーの入力したHTMLをそのまま入れてる場合に問題になるケースがあります。一ヶ月ぐらい前にIRCでそういう話になったときcho45がおしえてくれた。

cho45++

2007-08-30

TemplateToolkitでハッシュを使う時の注意

http://naoya.g.hatena.ne.jp/naoya/20070828/1188305840

ハッシュのキーの先頭が_だと取れなくなる、って話だけど、
それライブドアの社内IRCで去年の9月11日に散々既出のネタだよ。

ハッシュキーの先頭が.か_だとプライベートになって、itemだと取れなくなる。これはTTの仕様。
回避したいときは自前でプライベート関係なく値を取れるメソッドを定義してやればOK。
http://www.template-toolkit.org/pipermail/templates/2006-January/008206.html

バージョンごとの検証とかしてないけど多分これで平気なはず。

2007-08-04

RSSリーダーの性能、優劣とは、なにか

ブログの記事を読んで、その記事を書いた人のことを、面白く思ったり、好きになったり、もっと知りたくなったりしたときに、気兼ねなく追加できるかどうかだ。これが一番重要な性能だと思っている。

2005年、ギークたちはBloglinesを愛していた。技術系の集まりにちょくちょく顔を出すようになって分かった事は、みなBloglinesを使っていたということだ。自分のブログを読んでくれる人が多い事に驚いた。これはBloglinesでなければ、あり得なかったことだ。

なんだよ情報収集って。スパイや探偵じゃあるまいに。俺がフィードを7000件以上購読してるのは、知識を得るとか、仕事に役に立つとか、そんな理由じゃないよ。

とりあえず、これだけは先に書いとく。

2007-07-23

「ニコニコ動画のAmazon売り上げを鵜呑みにするのは危険」について

ARTIFACT@ハテナ系 - ニコニコ動画のAmazon売り上げを鵜呑みにするのは危険を読んで気になったこと。
予約とかキャンセル分とかも、もちろんあるとは思うけど。

やってる人なら分かると思うけど、Amazonのアフィリエイトは紹介した商品以外にも、ついでに売れた商品も売り上げとしてカウントされる。アフィリエイトID付きのリンクを介してAmazonにアクセスして1日以内に注文された商品が紹介料の対象になる。で、ある程度PVが多くなってくると、特定の商品を紹介しなくても単にAmazonにアフィリエイトID付けてリンクするだけで関係のない商品も結構な数売れるようになる。本を紹介しただけなのにDVDレコーダーが売れたりすることもある。

で、ニコニコ動画の場合だけど、ユーザー数やアクセス頻度が多くなればなるほど、元々購入予定だった商品にニコニコ動画のアフィリエイトIDが付く確率が高くなるわけなので、その部分の(元々売れるはずの商品の)売り上げについては「ニコニコ動画が売り上げに貢献した」とは言えないんじゃないかな。ニコニコ動画のユーザーがどれぐらいAmazonで買い物をするのか、という指標にはなるけども。

FirefoxやOperaの検索窓にはAmazonの検索ボックスが付いていて、デフォルトでAmazonのアフィリエイトIDも付いているけれど、Firefoxの検索ボックス経由でアニメDVDを買ったとしても「FirefoxがアニメDVDの売り上げに貢献しました」とは言わないよね。もしもGoogleの検索結果にAmazonのアフィリエイトIDがくっついていたとしたら「総取り」してしまうだろうし、IEにAmazonショッピング機能が付いてたら、アフィリエイトとかほとんど意味無くなる。ユーザーは単に手近なリンクを介して商品を購入しているだけで、それがきっかけで消費行動に結びついているとは言えない、と思う。

もちろんニコニコ動画が売り上げにプラスになったりマイナスになったりするのはあると思うけど、そういった影響とは関係なく、PVの多いサイトにAmazonのリンク張ってれば売れる物は売れる。数字を出して「ほら、売り上げに貢献してますよ」とアピールするのが目的なのだから、多少の誤解も計算の内だとは思うけれど、経済効果何億円とかそういういい加減な計算がまかり通るようになってしまうとすれば、それは「危険」だと思う。それから紫色の物を口に押し当てたハッカーがニコニコ動画ばかり見ているのも人類にとって多大な損失だと思う。こちらの問題についてはまた後日書くことにする。

2007-07-12

livedoor ReaderにはてなスターをくっつけるGreasemonkeyスクリプト

の、雛形。
http://la.ma.la/misc/userjs/ldr_with_hatenaster.user.js

(function(){
    var w = typeof unsafeWindow != "undefined" ? unsafeWindow : window;
    var initialized = false;
    var s = document.createElement('script');
    s.src = 'http://s.hatena.ne.jp/js/HatenaStar.js';
    s.charset = 'utf-8';
    document.body.appendChild(s);
    var t = setInterval(function(){
        if(w.Hatena){
            init();
            initialized = true;
            clearInterval(t);
        }
    }, 100);
    function init(){
        w.Hatena.Star.EntryLoader.headerTagAndClassName = ['h2', 'item_title'];
        w.Keybind.add('H', function(){
            new w.Hatena.Star.EntryLoader();
        });
    }
})();


Shift + Hを押すと現在見てる記事にスターを表示。JSON API直接叩いてもいいけど、仕様変更に対応しやすいように。

2007-07-10

Fastladderを使い始めた

livedoor Readerの海外版のFastladderがリリースされました。
どうやって使おうか微妙に悩んでたのだけれど、シンプルにFastladderに興味のある人のOPMLをインポートしまくって、livedoor Readerで購読しているフィードをFastladderから削除することにした。(逆でもいいけど既読管理とかあるので、追加分をFastladderに寄せた)

livedoor Readerで既に購読しているフィードのURLを保存する

livedoor Readerでスクリプトを実行する。Firebugとか、javascript:を付けてアドレスバーに貼り付ける。「既読フィードも表示」の状態で実行する。

feedlinkをJSONで保存
prompt("これをコピーする",subs.model.list.pluck("feedlink").toJSON());

サイトURLをJSONで保存。
prompt("これをコピーする",subs.model.list.pluck("link").toJSON());

Fastladderからlivedoor Readerで既に購読しているフィードを削除

こちらも「既読フィードも表示」の状態で実行。

フィードURLを一括で削除
(function(){var c=prompt("さっきの貼り付ける");if(!c)return;var d=eval(c);var m={};d.forEach(function(s){m[s]=1});var total=0;var p=0;var wait=100;subs.model.list.forEach(function(s){if(m.hasOwnProperty(s.feedlink)){new API("/api/feed/unsubscribe").post({subscribe_id:s.subscribe_id},function(){p++;message(total-p)});total++}}.later(wait+=100))})();


RSSとAtomを重複して購読してたりするのが多いので、それも削除する。サイトURLが同じフィードを一括で削除。ただし検索結果のフィードなんかでトップページのURLが同じになってるのがあるので、フィードに?を含まないものに限定して削除。

(function(){var c=prompt("さっきの貼り付ける");if(!c)return;var d=eval(c);var m={};d.forEach(function(s){m[s]=1});var total=0;var p=0;subs.model.list.forEach(function(s){if(m.hasOwnProperty(s.link) && s.feedlink.indexOf('?')==-1){(function(){new API("/api/feed/unsubscribe").post({subscribe_id:s.subscribe_id},function(){p++;message(total-p)})}).later(100*total)();total++}})})();


最初に試したときにブラクラになったのでウェイトを入れるようにした。ウェイト入れる位置違うけど、まあどちらでも動く。OPMLを使ってここら辺の操作を簡単にできるようにしておけばそれなりに需要があるような気がする。OPMLの差分を取ったり重ね合わせてレートを決めたり。

購読フィードは合わせて7000件ぐらいになった。