2011年 02月 02日



誰にも嫌われたくないみたいなのは全くなくなったけど、しかし限定した範囲ではまだそういうのがあってしばしば困る。それによって書けないこともでてくる。良くみられようとするってのはそれ自体が醜いことだし、言葉の節々に本性というのはでるので、百害あって一利もない。

知らない人とのコミュニケーションの仕方についてはよく考えるけど、知ってる人とのコミュニケーションの深め方みたいなのは全然考えていないなと思った。基本的に後者って「会って話せばいいじゃん」というものなので、インターネットでやる意味は薄いかなと思いつつ、そうはいっても物理的な距離があってどうしようもない場合もまたカバーすべきケースであり、しかし解決方法がさっぱりわからないので、困ったもんです。

2011年 02月 03日

gerry++

2011年 02月 04日



2011年 02月 03日

Android の WebKit はスタンバイ状態 (ディスプレイ消灯とか) から復帰したときに何かイベントを投げてほしいなあ……

2011年 02月 05日



Android のブラウザはディスプレイがついてる場合、フロントの Activity でなくなってもスクリプトが動き続ける

2011年 02月 06日


神社仏閣図集 1 /神社建築編 1 - 建築資料研究社

建築資料研究社

3.0 / 5.0

なんか、面白そうなので買ってみたけど、すごく買ってよかった。値段が高いのがネックですが、なんかもうわけがわからない面白さがあっていい。中身は淡々と図面で、殆ど説明とかは入っていない。

自分はその、展開図とか、意味もなく眺めたりするのが好きなんだけど、そういう面白さです。

2011年 02月 07日

tar で纏めるときの引数が覚えられません

「覚えられません」と書くと覚えられる法則に基づき「覚えられません」と書いておきます。tar xzvf の x を c に変えるだけなんだけど、そのあとの引数が覚えられない……

tar cvfz foo.tar.gz dir
2011年 02月 08日

どうするんだこれ……

ポカーンとしてる……

自分が保守的なためにウェブ側に集中しているのか、それとも単にウェブ側の技術が好きなのかってのはちょっと自分では判断できない感じです。

外に出ないものを作る気ってのはむしろ全くといっていいほどないんですけど、これはこれの問題があって、表に見える形を想像できないと手をつけられないとか、外に出ない可能性が高いだけでスピードが落ちるとか、特に後者は面倒です。

その外に出ない可能性っていうの、特に自分の裁量にないところでそれが起こったりするの、例えば iPhone アプリの審査とか、ああいうの、全く嫌で仕方なくて、とにかく質よりも量だと思うので、ヘタクソと罵しられようが、何も考えていないと言われようが、とにかく人の目に触れるところに何かがなければ何の意味も価値もないし、何の可能性も生まない感じ、外に出さないのはインターネット的じゃない。ゴミでもなんでも置いときゃいい。重要なものは勝手に浮いてくるのだ。

検索しきれないぐらい大量のリソースがあればいい。あるいは検索エンジンがしっかり成長して、人ごとに個別の検索結果を表示できるようになればいい。Google なんてもう SNS 作らなくなって、それよりもっとでかい SNS をインデックスしているのだから、誰かが見たい情報だけじゃなくて、誰かが見たいと思っていても、誰かがそういう人に見られたくないと思うことを考慮できたらいい。Analytics でユーザ傾向はとられているし、悪意のあるユーザやゲストユーザにはもはや感情の入らない情報だけが検索できれば良い。とにかく見つかりさえしなければ、強固なセキュリティやプライベート設定なんていらないのだ。広告属性が設定できるなら、ある属性の人の検索結果にだけページを表示させたい、というのは今だってできるだろう。

2011年 02月 07日

JetPack で複数のプロキシを切替えられるやつを書いてみた。

もともと userChrome.js で同じようなのを書いていたのだけど、Fx4 になって動かなくなったので、JetPack で作りなおしてみた。

Panel は他ウィンドウフォーカスすると消えてしまうので、普通の Window のほうがいい気がしたけど、やりかたがわからなかった。showModalDialog とかなのかもしれないけど、変にハマりたくなったので凝ったことはしてない、つもりだけど権限の問題で全体的に message のやりとりばかりになってしまう。仕方ないけど読みにくいですね。

今の JetPack Add-on sdk はよくできてて、セットアップして cfx init したあとは、cfx run を繰替えし、できたら cfx xpi すればいいので簡単 (cfx コマンドは SDK に入っている)

できた xpi はインストール時に再起動がいらない (Add-ons bar だけ再起動する) ので便利

2011年 02月 08日

gerry++

2011年 02月 09日


2011年 02月 10日

2011年 02月 11日

Chrome で XHR を abort() し続けるとそのうちリクエストが送信されなくなるのはどうにかならないのか

callback だけ無効にしてサーバサイドではちゃんとレスポンス返せってこと?

いまいち発生条件がつかめてないけど、ページロードしてからの累積回数で決まっているような気がしてならない。待ってても回復しない? というか abort() は自分でやってるんだから、余計なことしないでほしい。嫌なリクエストがくるならサーバ側ではじけばいいんだから……

以下のようなコードで再現する

上記の推測は間違っていて?、要は response body を待っている状態の XHR を abort() しても、Chrome はレスポンスを待ち続けるということらしい。HTTP ヘッダだけ先に送って body をストリームさせる場合にいろいろ困る。

#!/usr/bin/env corona
# vim:ft=perl:
use strict;
use warnings;
use Coro;
use Coro::Timer qw(sleep);

my $HTML = <<'EOF';
<!DOCTYPE html>
<html>
<title>test</title>

<h1>reproducing process</h1>
<ol>
	<li>Request to remote server
	<li>After requested, abort() it
	<li>Try requesting another xhr (but this waits until aborted xhr response)
</ol>

<textarea cols="140" rows="20" id="log"></textarea>

<script>
document.getElementById('log').value = "";
function log (m) {
	document.getElementById('log').value += m + "\n";
}

var seq = 1;
function req (time, callback) {
	log('req:'+seq++);
	var xhr = new XMLHttpRequest();
	xhr.open('GET', '/api/test?' + time, true);
	xhr.onreadystatechange = function () {
		log([ xhr.readyState, xhr.responseText ]);
		if (xhr.readyState == 4) callback();
	};
	xhr.send(null);
	return xhr;
}

function req_abort (time, callback) {
	var xhr = req(time, callback);
	// setup timeout to send request to remote surely.
	setTimeout(function () {
		log('abort');
		xhr.abort();
	}, 100);
	return req;
}

req(0, function () {
	req_abort(10, function () {
		req(1, function () { log('ok') }); // success after 10sec but should success after 1sec
	});
}); // success;


</script>
EOF

sub {
	my $env = shift;
	warn $env->{REQUEST_URI};
	my $sub = {
		'/' => sub {
			[ 200, [ 'Content-Type' => 'text/html' ], [ $HTML ] ];
		},
		'/api/test' => sub {
			sub {
				my $respond = shift;
				my $writer = $respond->([ 200, [ 'Content-Type' => 'application/json' ] ]);
				async {
					sleep $env->{QUERY_STRING};
					$writer->write('{ "ok": true }');
					$writer->close;
				};
			};
		},
	}->{$env->{PATH_INFO}};

	$sub ? $sub->() : [ 404, [ 'Content-Type' => 'text/plain' ], [ '404' ] ];
};

Chrome で 50x を数回受信すると throttle が有効になってリクエストを送信できなくなるが、どういった対策をうてばいいのか?

これは XHR にもあてはまってしまう。

マジでヤバい場合以外 50x を返さないということが必要になってしまう。バックエンドが応答できない場合特定のレスポンスを 200 で返したい、とかいうのは nginx でできるのか?

あるいはそもそも、1度 50x がでたらちゃんと待てばいいんだろうか?

2011年 02月 12日


建国記念の日、せっかくなので橿原神宮 (神話上で建国したことになっている神武天皇が祭神、橿原は建国の地ということになっていて、この神宮の創建は明治の、まぁ想像通りの時期です) にいってみた。とにかく右翼が多くて怖かったんだけど、外拝殿のところでそういう人ら並んで記念写真とってて「はい、チーズ」とかいっていたのがシュールだった。他もろもろ含めて面白かったけど、割と異様な雰囲気なので (祭なのでそういうもんだけど、それにしても)、あまり他人にはおすすめできない。

といってもそっちはメインではなくて、橿原考古学研究所附属博物館に展示されてる大型内行花文鏡を見たかったのでした。が、ピンポイントにその鏡は九州国立博物館に3月まで貸出中とのことで展示されておらず、小さい内行花文鏡しかありませんでした。日本最大の内行花文鏡は福岡で見れるみたいですけど遠すぎるので、鏡見るためにそのうちまた行きたいです。

2011年 02月 11日

gerry++

2011年 02月 13日


2011年 02月 12日

JavaScript の哲学

  1. 小さいものは美しい
  2. 各スニペットが一つのことをうまくやるようにせよ
  3. できる限り最小限のプロトタイプを作れ
  4. コード量よりも移植のしやすさを選べ
  5. 単純なオブジェクトにデータを格納せよ
  6. 最小限のコードで最大限のことをすることに優位性を見出せ
  7. 効率と移植性を高めるためにコールバックを利用せよ
  8. 束縛するインターフェースは作るな
  9. 全てのスニペットは限りなく独立して動くようにせよ

Mike Gancarz の UNIX哲学の改変です

2011年 02月 13日

gerry++

2011年 02月 14日


土曜日は雨が降りそうだったので、御苑にちょっといっただけだった。

日曜日もだいぶぼーっとしてしまったが、午後遅くなってから住吉大社に行こうという気持ちが高まったので行ってきた。久しぶりに行ったことない神社を開拓した気分。

住吉大社は今まで見てきたどの神社とも社殿の造りが違うので面白かった。平面的で力強い感じなのでその点で神明造りっぽい感じもしつつ、本殿の床が低く妻入りで拝殿が直結してるので全然違う印象になっていた。それと、本殿4つあるうちの3つ(住吉大神3柱)は直線に配置されているのに、4つ目は特に対称性がないところに建っていて不思議な感じだった。

『赤髪の白雪姫 』あきづき空太

赤髪の白雪姫1 (花とゆめCOMICS) - あきづき空太

あきづき空太

3.0 / 5.0

欲しいなー と思いつつ amazon に在庫がなくてなかなか買えなかったんだけど、ふと書店に立ちよったら普通に全巻売ってたので即断で買って、amazon 側をキャンセルした。

期待以上に良かったので買って良かった。主人公の女の子は意志が強くて可愛いし、薬剤師ってのも良いし、全体的に甘ったるさがただよわず、一貫して距離感がすっとしていて気持ち良いです。

この主人公の場合、意志の強さが過去の経験からきており (明確に描かれないけど多少辛いこと)、いろいろ考えた末にそう振る舞うのを良しとしているように感じられるので、単に意志が強いとか気が強いとかという生まれ持った性質ではなくて、むしろ形質によって崖に一度立たされたこその心持ちが見えて心にきた。

赤髪の白雪姫 2 (花とゆめCOMICS) - あきづき空太

あきづき空太

3.0 / 5.0


赤髪の白雪姫 3 (花とゆめCOMICS) - あきづき空太

あきづき空太

3.0 / 5.0


赤髪の白雪姫 4 (花とゆめCOMICS) - あきづき空太

あきづき空太

3.0 / 5.0


赤髪の白雪姫 5 (花とゆめCOMICS) - あきづき 空太

あきづき 空太

3.0 / 5.0

2011年 02月 15日


今日は朝からずっとイライラしてしまった。低気圧のせい(他人のせい)にしておきたいと考える。

ある種の、ちょっと変わった程度のろくでもない属性 (例えばある学校とか、ある世代とか、ある地域とか) を自分にラベリングすることで、何らかの個性を出そうという気持ちがすけてみえている感じ、ただそれだけなら、まだ求個性没個性なだけで気持ち悪くとも害はない (無意味で、無個性な誇りだ) けれど、その大して価値のないちょっと変わった程度のろくでもない属性を守るために、他人に対して攻撃的だったり、排斥しようという感じになってくると、一体なんなんだろうという感じに見える。

こういうこと、他人に対し、内側から強い気持ち悪さを感じるときは、大抵自分の中に何かしらそういうものがあるときだ。じゃあ、どんな類に対して自分がそういった馬鹿げたことを思うかと考えてみると「○○な人はクソであって欲しくない」みたいに言葉にするとき解りやすく表に出てくるのかもしれないと気付いた。「プログラマは」「日本人は」「Perl が好きな人は」「あるアーティストが好きな人は」とあてはめてみると、自分の中からわさわさと出てくる。結局これでは人のことが言えない。

他人に対するイライラは、日記にまとめているうちに、自分の普段の行いによって相殺されるか、自分にふりかかる。日記に書いて落としこむ時点で、自分のクズさに要約される。

何かしら書いてしまえば一貫性を求められる。破れば糾弾されるから、矛盾には先に自分で気付かなければならない。日記は読みかえされないといけない。でも考えかたが変わったら変わったと書けば良いだけだ。強い口調は、他人の機嫌を損ねるというより、自分の逃げ道をなくすから良くない。

高校・大学と人間が心底嫌いになるばかりにコミュニケーション能力を得る機会の多くを失なって、いろいろと困ることになったということも、それによって他人のコミュニケーションの仕方を冷静に観察できるようになったのであれば別にいいような気がするけれど、自分で考えて造れる良いものが、殆どの他人の望むものとは違うという話であるなら、全くなんのこともなくて、自分が価値 (他人が必要とするもの) を生み出せないことにほかならない。

そういう気概で一体どうして何か造れようかと思う。

こういったこと、他人ではどうしようもないので、仕方なく、未来の自分である他人が楽しければいいと考えるしかなくなる。

何かしら日記に書いていると、明日誰かに責めたてられる気がしてならない。クソだクソだと誰かが言っている声が聞こえてくる。おれがどんなにそういう人達に重さを感じないように努めても、不意うちでも何でも、視界に入ったら終わりなのだから、いよいよ、書くことで損することは認めないといけない。当たり前すぎるけど、インターネットは全然安全ではない。

jetpack は node.js と同じように、exports.foo = 以外にも this.foo = でもいけるようになっていて欲しかった……

Twitter でマジメな話ができないので、変な議論を呼びそうだなーとか、フローに流しても仕方ないこととか、ここに書いていこうという気持ちだけど、それに対して Twitter で返信されたらどうしたらいいのだろうなあ。追記するだけだと相手が気付かないし……

2011年 02月 16日


2011年 02月 15日

OGP、仕様的にフラグメントに対応できない問題があるし、そもそも hAtom っていう仕様が既にあるのでなんでわざわざ別のを定義したのかわからない

2011年 02月 16日

JSDeferred を Jetpack (Add-on SDK) で使う

binding を書いた (まだブランチに入れてある)

  • setTimeout/clearTimeout がないので nsITimer で実装 (これでいいのか?)
  • Deferred.postie という utility を追加

Deferred.postie(constructor, options) を使って widget/panel をつくるとメソッドが増えます。

  • post(args..., function) //=> Deferred
    • function をレシーバの content context 内で args と共に呼び、結果を取得
  • bind(selector, event, function) //=> Deferred
    • content 内の selector でマッチする要素全てで、 event が発火時 function (chrome context) を呼びだす

以下のように書けます。post に渡す関数は文字列化されて content に渡されるので、スコープを外部と共有していない。args も JSON で表現できるものしか渡せない。この点わかりにくいのでイマイチかもしれない。

完全に message のやりとりを置き換えられるわけではないけど、ちょっとしたイベント処理とかは直列で簡単に書けるようになるので、便利な場合は便利かもしれない。

const Deferred = require("jsdeferred").Deferred;
Deferred.define(this); //define 使う場合必ず引数に this を渡す必用あり

widget = Deferred.postie(widgets.Widget, {
	label      : "Foo",
	contentURL : 'http://example.com/',
	width      : 32,
	onClick    : function () {
		var self = this;

		next(function () {
			return self.
				post(1, 2, function (a, b) { // content context 
					return a + b;
				}).
				next(function (res) { // chrome context
					console.log(res);
				});
		}).
		next(function () {
			return wait(1);
		}).
		next(function () {
			return self.
				post(function (a, b) {
					throw "foo";
				}).
				next(function (res) {
					console.log(res);
				}).
				error(function (e) {
					console.log(e);
				});
		});
	},
	onMessage : function (message) {
		console.log(message);
	},
	contentScript : 'setTimeout(function () { postMessage("custom message") }, 1000)',
});

widget.post(function () {
	var d = new Deferred();
	setTimeout(function () {
		d.call(1);
	}, 1000);
	return d;
}).
next(function (a) {
	console.log("Hello! " + a);
}).
error(function (e) {
	console.log(e);
});

widget.bind("body", "click", function (e) {
	console.log("body clicked" + e);
}).
error(function (e) {
	console.log(e);
});
2011年 02月 17日



メッセージキュー、何を使えばいいのかわからないお……

Q4M って DBI 使うとブロックしちゃうけど、非同期にするにはどうしたらいいんだろう。AnyEvent::Worker|AnyEvent::DBI (=fork) 使うのがいいのかな。スタンダードな方法がわからない

LDR Streaming API では自力で MQ 作ったというのを見たけど、これ使っとけ的なのはないのかなあ……

Memo

2011年 02月 18日


2011年 02月 17日

HTTP ベースで pub/sub なメッセージキュー

かなりざっくり書くと以下のような感じになる気がするけど、こういう HTTP ベースの内部用途の pub/sub サーバって既に良いのはあるのかな……

package Buspub;

use strict;
use warnings;
sub route ($$);
use Router::Simple;
use Tie::IxHash;
use AnyEvent::HTTP;
use HTTP::Request::Common;
use JSON::XS;
use POSIX ();

use MongoDB;
my $connection = MongoDB::Connection->new(host => 'localhost', port => 27017);
my $subscriptions = $connection->get_database('pubsub')->subscriptions;
$subscriptions->ensure_index(Tie::IxHash->new( key => 1, created => -1 ), { background => 1 });

route '/sub' => {
	action => sub {
		my ($r) = @_;
		my $key = $r->req->param('key') or return $r->json({ error => "key required"});;
		my $callback = $r->req->param('callback') or return $r->json({ error => "callback required"});;
		my $id = $subscriptions->insert({
			key      => $key,
			messages => [],
			callback => $callback,
			max      => 25,
			created  => scalar time(),
		});
		LOG("SUB:: %s with callback: %s", $key, $callback);
		$r->json({ id => "$id" });
	}
};

route '/pub' => {
	action => sub {
		my ($r) = @_;
		my $key = $r->req->param('key') or return $r->json({ error => "key required"});;
		my $message = decode_json $r->req->param('message');

		my $cursor = $subscriptions->query({ key => $key });
		my %count;
		while (my $obj = $cursor->next) {
			$count{all}++;
			my $id  = $obj->{_id} . "";
			my $uri = $obj->{callback};
			my $messages = [ @{$obj->{messages}}, $message ];
			my $req = POST $uri, [ id => $id, messages => encode_json($messages) ];

			LOG("PUB:: => %s => %s with %d messages", $key, $req->uri, scalar @$messages);
			http_request $req->method => $req->uri,
				body => $req->content,
				headers => {
					map { $_ => $req->header($_), } $req->headers->header_field_names
				},
				timeout => 20,
				sub {
					my ($body, $headers) = @_;
					LOG("PUB:: <= %s <= %s with status:%d", $key, $req->uri, $headers->{Status});
					if ($headers->{Status} =~ /^2/) {
						$subscriptions->update({ _id => $obj->{_id} }, { '$pullAll' => { messages => $obj->{messages} } });
					} elsif ($headers->{Status} =~ /^4/) {
						$subscriptions->remove({ _id => $obj->{_id} });
					} elsif ($headers->{Status} =~ /^5/) {
						if (@$messages > $obj->{max}) {
							$subscriptions->remove({ _id => $obj->{_id} });
						} else {
							$subscriptions->update({ _id => $obj->{_id} }, { '$push' => { messages => $message } });
						}
					}
				}
			;
		}
		$r->json({ key => $key, delivered => \%count });
	}
};

route '/test/callback' =>  {
	action => sub {
		my ($r) = @_;
		use Data::Dumper;
		warn Dumper $r->req->param('id') ;
		warn Dumper decode_json $r->req->param('messages') ;
		$r->res->status($r->req->param('code') || 404);
		$r->res->content_type('application/json; charset=utf8');
		$r->res->content('{}');
		$r->res->finalize;
	}
};


BEGIN {
	my $router = Router::Simple->new;
	sub route ($$) { $router->connect(@_) };

	sub run {
		my ($env) = @_;
		if ( my $handler = $router->match($env) ) {
			my $c = Buspub::Context->new($env);
			$handler->{action}->($c);
		} else {
			[ 404, [ 'Content-Type' => 'text/html' ], ['Not Found'] ];
		}
	}

	sub LOG {
		my ($message, @args) = @_;
		print sprintf("[%s] $message", POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime), @args), "\n";
	}
};

package Buspub::Request;
use parent qw(Plack::Request);

package Buspub::Response;
use parent qw(Plack::Response);

package Buspub::Context;
use JSON::XS;

sub new {
	my ($class, $env) = @_;
	bless {
		req => Buspub::Request->new($env),
		res => Buspub::Response->new(200),
	}, $class;
}

sub req { $_[0]->{req} }
sub res { $_[0]->{res} }

sub json {
	my ($self, $vars) = @_;
	my $body = JSON::XS->new->ascii(1)->encode($vars);
	$self->res->content_type('application/json; charset=utf8');
	$self->res->content($body);
	$self->res->finalize;
}

\&Buspub::run;
2011年 02月 18日

Firefox、Mac OS X で2つ以上インスタンス化すると、-no-remote の有無に限らず最初に起動したほうが open http://.../ で使われるのはどうにかならないのか

バイナリもう1つ作って Contents/Info.plist のそれっぽいエントリを消したり、s/Firefox/XXXXX/g したりするとうまくいくようだ……

2011年 02月 19日

やる気のリハビリというの頑張ってやろうとしてもすぐ無駄にされるので、やる気なくなる悪いループにハマってる。

やる気のリハビリというの、どういうことかというと、大きなものを作ろうとすると大きなやる気が必要になるけど、それだけのやる気がないとき、小さなものを小さなやる気で作ってフィードバックを得て、小さいやる気をちょっとずつ増幅させていくということです。

これ、継続的に減衰させるような要素があると (例えば不安・不信とか) 全然次の段階に進まないし、永遠に小さいものを小さなやる気でつくるしかなくなる。あるいはやる気ってのは外敵に著しく弱いので、何かしらの刺激でゼロに戻ると、また最初から、つまり小さなものを作ることからやりなおしになる。

一旦育ててそれなりに大きいものを作れて、フィードバックを適切にうけられれば、さらに大きいものを作っていける一方、ゼロになると長い時間が必要になってしまう。

こういうこと、体内にやる気の永久機関を持っていて自己完結している人には理解されないのだろうなあと最近思った。

強烈なやる気を持って何か作ってるときは非常に幸せなのだから、やる気は徹底的に保護したいと思っているけど、うまくいかないもんですね。

モチベーションを保つのってめちゃくちゃ難しいことだと思うし、特に人から「やれよ」といわれてやることに対してのモチベーションなんて、二日持てばいいほうなんじゃないのかなぁと個人的に思う。

http://lowreal.net/blog/2006/09/27/2

なんかすんごい何度も書いてる気がするけど、モチベーションの維持が一番難しいのだ。だから自分はモチベーションがあるときは失わないように必死だし、モチベーションがないときはどうすればモチベーションがでるか考えている。

http://lowreal.net/blog/2007/01/02/1

成長してなくて笑えないです。体内にやる気を生成する機関がうまく作られなかったのでもうどうしようもない感あります。

悔しいって気持ちあんまり感じないんだよなあ…… ないし、感じるけど、人に対してはあんまり感じなくて普通にすごいなぁとしか思わない。あるいは悔しいと思っても、別にそれが行動に繋ったりしない。「残念だったねぇ」としか思わないし、「悔しさ」自体はモチベーションには繋がらない。

一番悔しいって感じるときは、アイデアがあって、実装もしてあったのに、先に誰かに同じアイデアの何かを出されたときですよ。例え同時多発的なアイデアであっても、後発は永遠にパクりの嫌疑をかけられるんですから。

この場合、そのとき「悔しい思いをする想像」っていうのは、早く実装して早く出したいという気持ちになるけど、もちろんそれは「これはおもしろいし先をこされたくない」っていう強い感情に基いてる。

2011年 02月 20日

2011年 02月 21日

2011年 02月 20日

gerry++

2011年 02月 21日

Android でウェブ側からアプリケーションを起動したいときのベストプラクティス

ウェブ側からリンクを貼って特定のアプリを起動させる場合、独自スキームを使うというのは自然な流れでまぁ普通そうしたい感じですが、対象アプリが入っているか否かをウェブ側から取得することができないため (できるの?)、アプリが入ってないユーザさんに対してブラウザのそっけないエラー画面になってしまうのであまり好ましくありません (アプリが入っていることがほぼ確実ならこれでいいけど)

現状でこの方法は簡単には解決できなくて、おそらく現状のベストプラクティス的には http を併用するのかと思っています。

  • fooscheme:openapp をアプリケーションでハンドリング
    • 確実にアプリが入ってることが判定できる場合に使う?
      • 普通にインテント使えばいいので、たぶんあんまり使うケースない……
    • スキーム無闇に増やすと怒られる
  • http://mydomain/openapp をアプリケーションでハンドリング
    • ウェブからアプリを起動したいときに使う
    • URLには「アプリケーションをインストールする」ページを作っておく
    • このURLにアクセスすると Browser とアプリ2つ表示されてしまうので、デフォルトでアプリを開くようにユーザを促す
        <activity android:name=".PostEntryActivity"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait" android:configChanges="orientation">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.ALTERNATIVE" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="fooapp" android:host="open"/>
                <data android:scheme="http" android:host="fooapp.example.com" android:pathPattern="/openapp"/>
            </intent-filter>
        </activity>

とはいえ、この方法モノリスでやるときにとろうとしたんですけど、何かがうまくいかなかった気がするので本当にこれでいけるか不安です。(今試した感じ想像通りに動いたので、うまくいかなかったのは当時の勘違いだったかもしれない。あるいは Android1.6 だとブラウザ内の http:// に関しては確実に Browser が制御を奪ってしまっていたような気がする)

2011年 02月 22日

アマゾンのうけとりわすれないように > 俺

CORE::qr が呼ばれないように正規表現パターンを定数化したら速くなった

Text::Xatena の nytprof 結果を眺めていたら CORE::qr がやたら呼ばれていたので、use constant で qr// をループの外に出したら速度が多少改善した。通常の正規表現マッチは勝手にいい感じに定数っぽくしてくれるけど、正規表現パターンはしてくれないのかな。

before
-Rate   Hatena  Textile Markdown   Xatena
-Hatena   26.8/s       --     -84%     -86%     -89%
-Textile   171/s     537%       --      -8%     -27%
-Markdown  186/s     594%       9%       --     -20%
-Xatena    233/s     770%      37%      25%       --
after
+           Rate   Hatena  Textile Markdown   Xatena
+Hatena   26.5/s       --     -85%     -86%     -93%
+Textile   175/s     563%       --      -8%     -56%
+Markdown  191/s     621%       9%       --     -52%
+Xatena    395/s    1393%     125%     107%       --
2011年 02月 23日



gerry++

2011年 02月 24日


2011年 02月 25日

2011年 02月 26日

2011年 02月 25日

prototype と new がダメってどこ情報よ〜

2011年 02月 27日


2011年 02月 26日

gerry++

2011年 02月 28日


インターネットで情報を直接受け取って判断できるようになったんだから、もう「メディアが煽ったせいで」なんて言い訳は通用しなくなる。

Benchmark.javascript

Benchmark.javascript - jsdo.it - share JavaScript, HTML5 and CSS

ベンチマーク計るやつを jsdo.it に置いときました。jsdo.it だと HTML も含めてセットにできるのでいいですね。Fork していくつか関数を定義するだけでベンチ計れるので、ぜひお使いください……

(jsdo.it のブログパーツがはれるようになったみたいですね)