2008年6月25日水曜日

そろそろ知ってもいいんじゃないかな、PS3がどれだけ凄いかを

このブログ記事をはてなブックマークに追加

一年以上前に、PLAYSTATION 3を購入した。このときは、Cellでアレゲに遊ぶぐらいのつもりだったのだが、どうしてどうして、PS3がここまで凄いとは。これは嬉しい誤算だった。ここ数年で買ったものの中でもっとも満足度の高い製品だ。そして、こんなに素晴らしいものを多くの人は知らないで(もしくはマスコミなどの偏見に騙されて)、使わずにいるなんて損をしているなぁ、と思ってしまうのだ。

ここではPS3の良さを述べているわけだが、私は別にソニー製品のファンというわけではないし、基本的にメーカーにはこだわらない方だ。良いものは良いし、悪いものは悪いのである。現在使っているノートPCはPanasonicだし、ヘッドホンはBoseだし、ディスプレイは三菱で、デスクトップPCはBTOだ。ゲーム機にしたって任天堂製品も使っている。節操がないようにも見えるかもしれないがそれぞれ自分なりに吟味して選んだものばかりなのだ。例えば、ノートPCはNEC、ソニー、Dellなどを使ってきているし、ヘッドホンもいろいろと購入している。BTOのPCにしても複数のショップから購入してどの店はどの点が良くてどの点が悪いのかを自分なりに分析している。とにかく自分で多くの製品を使ってみて、納得の行く本当に良いものだけを残すようにしているのだ。もちろんそのときは最高のものだと思っていても後でより良いものが出てきたりするわけだが。

しかし、世の中の多くの人々が、マスコミやネットの情報に踊らされ、自分では何一つ確かめていないのに、さも知っているかのような感覚に囚われ、良いものを悪く、悪いものを良く感じてしまう。しかも、悪いものしか知らないから本当に良いものが理解できないのだ。これは何もPS3に限ったことではなく、自分の周りだけ見ても様々なレベルで日常茶飯事に起こっていることだ。まずは、周りの情報に踊らされることなく、自分の目、耳、手を使って情報を集めて欲しい。本当に良いものが埋もれてしまうのはすべての人の不幸である。

もっとも、PS3に限っていえば、埋もれてしまうことはなさそうだ。出だしは芳しくなかったPS3も、ゲームソフトなどが充実し、安価になってきて、良さがだんだんと伝わり始めたようで、ここのところの売り上げは好調らしい。別にPS3が売れたからといって自分にとっては直接の益があるわけではないのだが、もし売れないと、このような本当に良い製品が次回に繋がらないで世に出る機会を失ってしまうかもしれない。それを懸念しているわけである。

前置きが長くなったが、PS3は実際のところどうなのか。

私は平均して大体一日一回は起動している。別に毎日ゲームしているというわけではなくて、「まいにちいっしょ」内でニュースが配信されるからだ。世の中のちょっとした情報を知るのになかなか良い。トロとクロの掛け合いも和むし面白い。因みにこれは無料のコンテンツだ。また、ゲームソフトは複数持っているが、「アンチャーテッド エル・ドラドの秘宝」あたりを最初にプレイするのが良いだろう。あまり人を選ばないと思うし、非常に面白かったからだ。ほかにも多くの体験版がPLAYSTATION Networkから無料でダウンロードできるのでそれで遊ぶだけでもかなりのボリュームがある。

PS3はAV機能がありえないほど充実している。Blu-ray(BD)はもちろんのこと、BD-Live対応DVDのアップコンバート機能、インターフェイスにしてもHDMIや光デジタルなどなんでもござれだ。特に、BDについては一度フルハイビジョンで鑑賞して欲しい。DVDが観られなくなるほどだ。実際、自分はBDの画質を知ってからはDVDを買わなくなってしまった。それほど違いがありすぎるのだ。

ほかにDLNA(メディアサーバ機能)としても活用している。これを使えば、PCで録画した番組をPS3を通して自由に再生することができる。PS3上で表示できることはもちろん、PS3から無線LANやインターネットを介してPSPで観ることもできるのだ。PSPからPS3の電源を立ち上げることができるので、PS3の電源をつけっ放しにする必要もない。

これらのAV機能はどうせゲーム機のおまけだろうと考える向きもあるかもしれないが、スーパーコンピュータの代わりにもなるほどのPS3に搭載されているCellの機能を生かすことで非常に高性能になっている。AV機器としてみれば30万円の価値があるとも云われるほどだ。BD-LiveなどでもPS3で利用できるグラフィカルなエフェクトが、ほかのBDプレーヤーでは力不足のため表現ができなかったりするぐらいだ。

以下、参考サイトを挙げておく。

PS3を購入する、これだけの理由
PS3をAV機器として評価する(前編): 進化するAVプレーヤー、PS3
PS3をAV機器として評価する(中編):“AVプレーヤー”にとどまらないPS3
PS3をAV機器として評価する(後編): 本格AVシステムへも展開するPS3

もし、PS3を持っている知り合いがいるのなら、是非使わせてもらおう。フルハイビジョンTVとAV環境が整っていれば尚良い。その上で自分自身で判断をしてもらいたい。

続きを読む...

2008年6月23日月曜日

ビューティフルコードとmalloc/free論争

このブログ記事をはてなブックマークに追加

このビューティフルコード(Beautiful Code)は悶絶するほど凄い本だ。著者には、カーニハンを筆頭に世界中のGuruたちが並ぶ。個人的には、高速ビットカウントやNumPy、MapReduceあたりに興味を覚えた。コードを書く人なら興味を覚えるテーマが一つや二つは必ずあるだろう。

しかしながら、私にとってはビューティフルコードの価値の1/3は、久野靖さんとまつもとゆきひろさんの対談にある。これは凄いよ。ずいぶん前、fj.comp.lang.c++で大規模なフレームがあった。malloc/freeについての論争である。mallocでメモリを確保した後にfreeをしなければならないのか、そうではないのかという、今でも時々蒸し返される定番の話題だ。

この当時、初心者にはmallocと対応させてfreeをすることを教えない方が良いとする意見がGuruたちの間では優勢であり、その中の一人にまつもとさんもいた。一方、久野さんは教えるべきだとの意見だった。前々からfjでの久野さんの意見はほとんど自分と一致していて、そして自分にとっては一々が説得力を持っていた。このときのmalloc/freeの意見でも完全に久野さんと同意見だった。malloc/freeについての主義や主張をここで繰り返しても仕方がないので、あとはC FAQでも読んで欲しい。云いたいことは、自分にとってこの時期がプログラミングに対しての考え方を形成する上で重要であったということだ。

現在、自分はメインのLLとしてPythonを使っている。これは上記のフレームが影響しているのだ。malloc/freeについて自分と異なる考え方を持つまつもとさんはRubyの作者であったが、私がRubyではなくPythonを選んだのはまさにこの考え方の違いのためだった。個人的には、Rubyの方がよりオブジェクト指向としての完成度が高いし、短く書ける(内包表記はまた別だけど)ので、好みに合うように思うのだが、やっぱり作者の考え方が自分と違うことを知ってしまうと喜んで使うことができなくなるのだ。今ならもう少し柔軟な考えもできるが、当時はまだ若かったこともあってどちらも使うという選択にもならなかった。

そして、久野さんとまつもとさんの対談をあの当時の懐かしさと一緒に読んでみた。型に対する意見の違いなど、やっぱり本当のプログラマは自分自身の意見をしっかり持っており、容易にそれが変わることがないのだなという雰囲気が伝わってきた。

こんな素晴らしい本を読める今のプログラマたちは幸せだと思う。

続きを読む...

2008年6月22日日曜日

ファイルの管理ってそんなに大変?

このブログ記事をはてなブックマークに追加

たまにPCに入っているファイルを探し出すのが大変だと聞くことがある。また、OSの機能としてファイルの検索機能について大きく取り沙汰されることがある。それだけ、ファイル検索については世間で関心が持たれているのだろう。

しかし、個人的にはその感覚がよく分らない。PCの個人フォルダには10万件近いファイルを入れているが、ファイルを探し出すのに困ったことはほとんどない。逆に何でファイルを探し出すだけのことにそんなに苦労するかが分らない。

新しいPCを購入した時にまず行うのがディレクトリ(フォルダ)の作成だ。ホームディレクトリには必ず以下の7つのディレクトリを作成することにしている。そして、このディレクトリ以外はいかなるファイルも恒常的には置かないことにする。ただし、Windowsの設定ファイル(隠しファイル属性)やUnixのドット(.)ファイルなどはこの限りではないが。また、researchというディレクトリがあるが、私の場合、仕事=研究なのでこのようになっている。

bin data develop document network research temp

それぞれのディレクトリは複数のサブディレクトリを持つ。それぞれをさらに分類するわけである。その分類の方法は該当するファイルの性質による。大抵はプロジェクト毎だとか、ジャンル毎で分けるが、日付が重要なものであれば日付で分ける。こうして分けておけば、取得したいファイルが何かさえ知っていれば迷うことはないと思う。もし、どうしても二つもしくは複数にまたがるような種類のファイルになってしまう場合は、コピーして同じファイルを持ったり、リンクを張ったりして、複数のファイルを持つことにしている。これで、どちらか一方で検索しても探し出せるわけだ。

また、Windowsでのフォルダ管理は別途ユーティリティを入れないと扱いづらいので、私はFileVisorを使って管理している。基本的にはエクスプローラと同じような感じであるが、様々なところで使いやすくなっている。特に、ファイルの中身検索やクイックアクセス、ファイルのアーカイブなどが便利だ。たとえば、多数のファイル群で構成されるプログラムコードの中から指定の変数などを探す場合、そのディレクトリ内から簡単に探し出すことができる。また、フォルダがある程度の深さの階層になっている場合もクイックアクセスを設定しておけば一発で開くことができる。

ここに示した方法は個人での管理の方法なので、複数の人が関るプロジェクトのファイルではバージョン管理システムなどを使うのが良いかもしれない。

続きを読む...

2008年6月20日金曜日

ActionScript 3.0のコーディング規約

このブログ記事をはてなブックマークに追加

最近、ActionScript 3.0のコーディング規約を知った。

Flex SDK coding conventions and best practices
ActionScript 3.0 コーディング規約の日本語訳

これが正しいとすると、自分の書いたコードは結構間違っていたりする。こういった規約が定まっているなら今度からはこれに従ったほうが良さそうだ。

基本としては、アンダースコア方式(単語と単語の間にアンダースコア_を挟む。例…underscore_style)は使わないで、クラス名にアッパーキャメルケース(UCC、単語の先頭を大文字にして連結させる。例…UpperCamelCase)、メソッド、変数、パッケージ名などにローワーキャメルケース(LCC、単語の先頭を大文字にして連結させるが最初の文字だけ小文字にする。例…lowerCamelCase)を用いるようだ。あとは、パッケージ名は名詞で、メソッドの先頭は動詞を使うとか。

個人的にはあまりLCCは好きじゃないんだけどな。でも、プログラム言語によってコーディングスタイルをかなり変えているにも関わらず、あまり混乱することはないなぁ。行末の「;」などは時々間違えることがあるけど。

続きを読む...

2008年6月18日水曜日

God of War: Chains of Olympusを終えて

このブログ記事をはてなブックマークに追加

とても面白かった。さて、どこが面白かったのか。たとえば、PSPとは思えない素晴らしいグラフィックやその動きだとか、ダイナミックな演出による爽快さだとか、息をつかせぬアクションシーンだとか、読み込み時間や保存時間がほとんど存在しないスピーディさとか。いくつも挙げられることができるだろう。でも、それらが単独で存在していたとしても、面白さは限定的なものになってしまう。本当の面白さはそれらが統合されて初めてわかるものだからだ。同じぐらいに面白い要素が入っていたとしても、それらがうまく組み合わさっていないとつまらないものになってしまう。いくら高級素材がふんだんに使われていても料理が下手ならまずくなってしまうのと一緒だ。

高級素材を使っているにもかかわらずあまり美味しくない料理が多い中、このGod of War: Chains of Olympusは間違いなく一流の料理だった。日本語版であるゴッド・オブ・ウォー 落日の悲愴曲は7月10日に発売予定だが、過度な暴力シーンや胸も露なエロティックな表現は若干削られると思うので、少し薄味な料理になるかもしれない。しかし、京料理が美味しいように、日本語版も面白いことは間違いない。

というわけで、実際に食べてみるまでその美味しさはわからない。プレイしてみなければその面白さはわからないだろう。

続きを読む...

2008年6月15日日曜日

ゲームを楽しめる人はマルチタスクのニュータイプ

このブログ記事をはてなブックマークに追加

ここのところゲーム関連の記事を書かなかったが、ゲームを楽しむことを忘れたわけではない。確かに最近は忙しくてほとんどゲームをプレイする余裕はなかったが、それゆえ、ゲームというのはとても贅沢な趣味であることを再認識させられた。

ゲームは人の感性に訴えるものであり、日常の中の非日常であり、それゆえ適度な刺激をもたらしてくれる。よりゲームを広く捉えるならば、それらは様々な感覚を要求し、人としての意味さえ問いかけてくる。人類は有史以来、すべてにおいてゲームの上のコマでしかなかった。生存競争から経済社会、友達との会話まで、ゲームの支配していないところなどないといっていいくらいに、人と深く関り合っている。そんなゲームを(コンピュータゲームに限ったものだとしても)ゲーム脳と云う似非科学をもって断罪することなど決してできはしまい。

なんだか話が逸れた。今ある生活がメインのゲームだとすると、それ以外のゲームを楽しむ人は、それだけ心に余裕があり、適応能力が高い人だといえる。ゲームを全否定する人は、シングルタスクの古い人間、楽しめる人はマルチタスクのニュータイプともいえるのではなかろうか。

プレイもしないで「暴力ゲーム」を非難しないでを読んだので書いてみた。勢いでニュータイプって書いたけど、ゲームを楽しめる人は大昔からちゃんといるよね。

続きを読む...

2008年6月14日土曜日

Google App Engine: まさに今、流行っていること

このブログ記事をはてなブックマークに追加

急上昇キーワード - 思いつきLab.でGoogle Trendの急上昇ワードを取得するAPIを知ったので、急上昇ワードを表示させるウェブアプリを作ってみた。

まさに今、流行っていること

オリジナルでは表示されない、変動の矢印、順位、前回の順位、それにスコアなどの表示を入れて、PCで見やすいものにした。さらに、Googleでキーワード検索、画像検索、Wikipediaで用語を調べられるようにした。

内容は大したものではないが、問題になったのは、xml.dom.minidomのparseだ。ローカル環境では、pyexpatがimportできず、エラーが出て実行できないのだ。サーバ側では問題ないのに。少し調べたところ、SDK1.0.2でいったん直ったらしいが、最新のSDK1.1.0ではまたエラーが出るようになったみたいだ。正式にリリースされたGoogle App Engineではあるが、SDK周りはまだbuggyな感じだなぁ。

処理部分のクラスの実装は以下の通り。あまり考えずにざっと書いたので汚いかも?

class Trend(webapp.RequestHandler): def get_text(self, nodelist): rc = "" for node in nodelist: if node.nodeType == node.TEXT_NODE: rc = rc + node.data return rc.strip() def handle_trend(self, trend): items = trend.getElementsByTagName("item") update = self.get_text(trend.getElementsByTagName("update")[0].childNodes)[:19] t = time.strptime(update, "%Y-%m-%dT%H:%M:%S") delta_update = (datetime.datetime.utcnow() - (datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5]) + datetime.timedelta(hours=7))).seconds / 60 return self.handle_items(items), delta_update def handle_items(self, items): data = [] for item in items: data.append(self.handle_item(item)) return data def handle_item(self, item): data = {} # query, rank, prev_rank, score, snippet, src for node in item.childNodes: if node.nodeType == node.ELEMENT_NODE: data[node.nodeName] = self.get_text(item.getElementsByTagName(node.nodeName)[0].childNodes) if node.nodeName == "query": data["urlencode_query"] = urllib.quote_plus(data[node.nodeName].encode("utf-8")) elif node.nodeName == "snippet": data["src"] = node.getAttribute("src") rank = int(data["rank"]) if data.has_key("prev_rank"): prev_rank = int(data["prev_rank"]) else: prev_rank = 1000 if rank < prev_rank: data["arrow"] = "<span style=\"color: red;\">↑</span>" elif rank > prev_rank: data["arrow"] = "<span style=\"color: blue;\">↓</span>" else: data["arrow"] = "←" return data def get(self): r = urlfetch.fetch("http://www.google.com/m/services/trends/get") dom = minidom.parseString(r.content) data, update = self.handle_trend(dom) template_values = { "data": data, "update": update, } path = os.path.join(os.path.dirname(__file__), "trend.html") self.response.out.write(template.render(path, template_values))

そして、テンプレートの表示部分は以下のようにした。

{% for d in data %} <div> <h2>{{ d.arrow }} {{ d.rank }} ({% if d.prev_rank %}{{ d.prev_rank }}{% else %}-{% endif %}) <a href="{{ d.src }}">{{ d.query }}</a><span style="font-size: x-small;">{{ d.score }}</span></h2> <p style="color: rgb(20%, 20%, 20%); text-indent: 16px; line-height: 140%;">{{ d.snippet }}</p> <p style="text-align: right;"><a href="http://www.google.com/search?q={{ d.urlencode_query }}">検索</a> | <a href="http://images.google.com/images?hl=ja&q={{ d.urlencode_query }}&gbv=2">画像</a> | <a href="http://ja.wikipedia.org/wiki/{{ d.urlencode_query }}">用語</a></p> </div> {% endfor %}

追記(12/1):

しばらく前から英語版になっていたのを日本語版に修正。http://www.google.com/m/services/trends/gethttp://www.google.co.jp/m/services/trends/getに変更した。ついでに夏時間対策も。

続きを読む...

2008年6月11日水曜日

Google App Engine: Memcache APIはローカル環境で使える?

このブログ記事をはてなブックマークに追加

勉強がてら簡易掲示板をMemcache APIによる分散メモリキャッシュに対応させてみた。確かに一度キャッシュすればデータベースへの読み込みは行われず、無駄なアクセスが減っていい感じに。

でもmemcacheってサーバ側ではちゃんと動いているのに、ローカル環境では動かないんですけど。キャッシュしなくてもいいから単なるエミュレータとしてでも動いて欲しい。それとも自分の使い方が間違っているのかなぁ。memcachedを使うのは初めてだし、データベース関係もほとんどいじったことないので自信なし。ローカルでテストできないとちょっときつい。とりあえず、try~exceptで対応しているけど…。

そういや、無理やりデータベースから一部データを消去した後、アプリケーションを読み込むと、memcacheのところで時々エラーが出るなぁ。エラー処理しているから表には出ないけど。一応、外部から一部データを消去したイリーガルなデータベースでもエラーが出ないような処理にしていると思うんだけど、何でだろ。

うーん、まだまだ勉強不足か。

続きを読む...

2008年6月10日火曜日

Google App Engine: urlfetchでのタイムアウト

このブログ記事をはてなブックマークに追加

urlfetch.fetchでサーバからデータを取ることができる。POSTやGETによるデータの送信もできる。しかし、fetchでは大体5秒ほどでレスポンスが返されないとそこでタイムアウトしてしまう。しかもこの制限は変更することができないのだ。困る。

fetchがタイムアウトすると、DownloadError()が返されるので、受け取って何とか処理を続行するか、もしくはECMAScriptなどによるレスポンスを照らし合わせて正しい処理を行うことになる。しかし、何度もリクエストを送ることができない処理、たとえば掲示板にPOSTでデータを送る場合などでは、なかなか難しい。

と云うわけで何かうまい解決法があったら知りたい。

続きを読む...

2008年6月8日日曜日

Google App Engine: Twitter送信機能付き掲示板

このブログ記事をはてなブックマークに追加

先日、Google App Engineで簡易掲示板を作成したが、ほとんどの書き込みが自分自身の“つぶやき”であることに気がついて、これだったらTwitterにそのまま送信してもよさそうだと考え、作ることに。しかし、思ったよりも苦労したのだった。

まず最初、Twitter APIを使って以下のような実装を考えた。

import urllib, urllib2 def main(): top_url = "twitter.com" url = "twitter.com/statuses/update.xml" username = "username" password = "password" passman = urllib2.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None, top_url, username, password) authhandler = urllib2.HTTPBasicAuthHandler(passman) opener = urllib2.build_opener(authhandler) urllib2.install_opener(opener) params = urllib.urlencode({"status": "つぶやき".encode("utf-8")}) pagehandle = urllib2.urlopen("http://" + url, params) if __name__ == "__main__": main()

しかし、これはurllib2でsocketを使うのでGAEの制限に引っ掛かりアウト。そこで次はネットなどで情報を集め、以下のようなurlfetchを使った実装を試みた。

url = "http://twitter.com/statuses/update.xml" payload = urllib.urlencode({"status": "つぶやき".encode("utf-8")}) base64string = base64.encodestring("%s:%s" % ("username", "password"))[:-1] headers = {"Authorization": "Basic %s" % base64string} result = urlfetch.fetch(url, payload=payload, method=urlfetch.POST, headers=headers)

これは、ローカル環境ではばっちり動作したので、そのままアップロード。だがしかし、ここで落とし穴が。実はGAEからのTwitterへの送信はすべて遮断されているらしい。がっくし。リファラ回りをいじってもダメだった。

しかし、ここまで来ては諦めきれないので、自分の持っている別のサーバに最初に挙げたコードをCGIとして実装し、GAEからそのサーバにデータを飛ばすことでTwitterへの送信を行うことにした。まあ、これで何とかなりはしたが、あまりすっきりしないなぁ。

最後に、Twitter送信機能付き掲示板の簡単な説明をする。メッセージボードにGoogleアカウントでログインすると、名前の横に[Twitter]のリンクが出る。そこからTwitterのアカウント情報を入力。この情報はサーバには送信されず、ローカルのクッキーに保存される。情報を入力すると、書き込みボタンの横の「Twitterに送信」チェックボックスがアクティブになるのでそれをチェックする。これで、掲示板への投稿と同時にTwitterにも送信される。ただし、全体で160バイト以内で[link]や[code]タグを含まないようにしなければならない。また、正しく送信されると書き込み記事の名前の横に水色のTの文字が表示される。

続きを読む...

2008年6月4日水曜日

Duff's device

このブログ記事をはてなブックマークに追加

仕事で使うコードの最適化について考えていたら、ふと、Duff's deviceが思い浮かんだ。仕事で使うコードとはまったく関係ないんだけど。

Duff's deviceは以下のようなコードである(Wikipedia英語版から若干修正)。

void strcpy(register char *to, register char *from, register count) { register n = (count + 7) / 8; switch (count % 8) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while (--n > 0); } }

要は、switch文のfall-throughを利用したループ展開による効率の良いメモリコピーだ。因みに、上記のコードで to に対してインクリメントがされていないが、出力レジスタへのコピーなのでこれで正しい。

効率的だといってこのコードを普段から利用するのはあまり良いとは云えないと思う。可読性が良いわけではないし、最近のコンパイラは最適化が進んでいることもあり、場合によっては速くならないことも考えられる。個人的には、このコードはswitch文におけるfall-throughの端的な例として見せるに留めるのが良いように思う。

続きを読む...

2008年6月3日火曜日

Google I/OでのAndroidデモ

このブログ記事をはてなブックマークに追加



Androidについて、Google I/Oデベロッパーカンファレンスで行われたデモを見たけど良さそう。端末のアンロックにパスワードではなく、タッチパネルをなぞってパターンを認識させる方法は面白いと思った。Androidじゃなくてもここまでサクサク操作できる携帯電話があったら是非欲しいものだ。

以前、ここのブログでも紹介したように、開発はJavaで行われる。Androidのアプリケーションを作ってみたいけど、いくら開発するのに言語は関係ないといっても、どれもこれも全部違う言語だと大変だなぁ。現在、C/C++, Python, ActionScript3のほかに、仕事ではFortranも使っているし。しかも、言語だけを覚えていればいいというわけではなく、それの開発に必要なライブラリや既存のコード、そして環境についても知っておかなくてはならないわけで。うーん。

なんか話がずれてしまったけど、Androidには今後も注目していきたい。

続きを読む...