大下さんと「宮廷のみやび 近衛家1000年の名宝」という特別展(東京国立博物館 平成館)を見に行きました。その名の通り近衛家という公家に伝わる様々な美術品が展示されています。
近衛家は、かつての摂関政治を牛耳り「日本は俺の物ですが何か?」と言い切った藤原家の流れを汲んでいる、いわゆる超名家ってやつです。一般人には縁もゆかりもありません。
中には「いよぉ、元気でやってる?」くらいの手紙も大層に飾ってあります。それでも書いた人が貴族とか天皇とか上皇ともなると、美術品の一種となるのでしょうね。
美術品はいまいち分からないものが多いのですが。今回見た中では近衛家熙(※1、※2)の「隷書心経」に感動しました。字がうますぎて、最初、印刷か何かだと思ったさ。家熙は何でも屋さんだったみたいですが、書家としてかなり有名みたいです。
賀茂人形や銀細工雛道具といった細かく小さい細工品が飾ってあるのを見ると、今も昔もそしてこれからも相も変わらず、日本人は小さくてかわいい物が大好きなんだなと思います。その形は変われども。国民性ですねえ。
(※1)このえ いえひろ [1667-1736] 、江戸時代の公家。Wikipedia「近衛家熙」の項を参照のこと。
(※2)(2/18更新)「ひろ」の字が環境によっては豆腐に…と書いていましたが、日記をアップデートした段階(EUC-JP -> UTF-8の変換)で潰れて出ていませんでした。諦めて当て字を書いておきます。
このキーワードでピンと来た方はこの日記を読む必要はないと思います。
Genericsなクラスにcloneメソッドを作ろうとしてはまりました。以下のようなコードを書いたわけです。
class MyVector<T extends Cloneable> implements Cloneable {
T[] items;
public Object clone() {
MyVector<T> copy = new MyVector<T>();
for (int i = 0; i < items.length; i++) {
copy.items[i] = (T)(items[i].clone()); //error!!
}
return copy;
}
}
Cloneableを継承する型だと宣言したところでCloneableインタフェースにはclone() の定義がありません。コンパイラはこのコードを見てもTがpublicメソッドのclone() を持っているのか、いないのかコンパイル時に判断できません。
従ってこのコードを実行すると基底クラスのObjectクラスのclone() メソッド(privateメソッド)が呼ばれる可能性があります。そのためコンパイラは「(Objectの)clone() はpublicじゃないから呼べません」とエラーを出すのです。
clone() を呼ばずに、以下のようなコードに直せばコンパイルが通ります。しかしこのコードで生成されるTのコピーはあくまでも「シャローコピー」ですから、Tがシャローコピーでコピーしきれない要素を持っていたときに破綻します。
copy.add(get(i)); //OK
配列の要素まで「ディープコピー」をするには、Tにclone() 関数の定義を強制させる必要があります。これにNewCloneableとでも名前を付けますと、以下のようになります。
public interface NewCloneable extends Cloneable {
public Object clone();
}
class MyVector2<T extends NewCloneable> implements Cloneable {
T[] items;
public Object clone() {
MyVector2<T> copy = new MyVector2<T>();
for (int i = 0; i < items.length; i++) {
copy.items[i] = (T)(items[i].clone()); //OK
}
return copy;
}
}
新しく作ったMyVector2クラスは「ディープコピー」ができるようになりました。しかしこのクラスは全く使い物になりません。なぜならNewCloneableを継承するクラスは標準クラスライブラリに存在しないからです。つまり何を言っているのかというと、
MyVector<Integer> v1; //OK
MyVector2<Integer> v2; //error!!
MyVectorと同じ乗りでMyVector2を使おうとすると「IntegerはNewCloneableを実装してないからダメ」と怒られます。せっかくのGenericsなのに自分で作ったクラスしかぶち込めないんじゃ、ちょっとあんまりですよね。
それならと、Integerを継承してNewCloneableを実装したクラスNewIntegerを定義しよう!と思ってもIntegerはfinal宣言されていて継承できません。MyVector2はますます役立たずです。
結局はシャローコピーで我慢せよってことですかね。もしくはclone() なんか実装すんじゃねーよってことでしょうか…。
目次: 自宅サーバー
PukiWiki 1.4.7に関連するページへのリンクを表示するrelatedというプラグインがあります。リンクには二種類あって、
が表示されるようになっています。
PukiWikiの編集時にブロック型プラグイン形式 #relatedか、index.php?plugin=related&page=PageNameのように(便宜的に直起動と呼ぶ)してpluginを呼び出すことで上記の機能が発動します。
どちらの起動方法でも機能は同じ……そんなふうに考えていた時期が俺にもありました。
バキネタはさておき、relatedプラグインってば直で起動するとブロック型とは別の処理が走ってしまいます。そのせいで順リンクが出ません。なんだこれ。
PukiWikiなんてそこら中で使われてるし、relatedの妙な動きにも誰か気づいていそうなもんですが…、そもそもどちらの動きが正しいんでしょう?それによっては以下のエントリが丸々無駄になる可能性があったりなかったり。
PukiWikiで「ひらメソッド」をやってみると、ある関数が誰を呼ぶか?という一覧の他に、ある関数が誰から呼ばれ得るか?ってのも知りたくなりませんか?
その手の情報は手動で管理すると死ねるので、逆リンクの一覧をページに埋め込むってのが欲しかったわけです。しかしながら #relatedでは、先述したように順リンクが混ざってうまくないです。
relatedを直すとあちこちに影響が出そうなので、今のところは、以下の図のような対象ページの逆リンクだけをすっぱ抜いてくるbacklinksプラグインを追加して凌いでいます。
<?php
// PukiWiki - Yet another WikiWikiWeb clone
// Backlinks plugin: Show backlinks for the page
function plugin_backlinks_convert()
{
global $vars;
return make_backlinks($vars['page'], 'p');
}
function make_backlinks($page, $tag = '')
{
global $script, $vars, $rule_related_str, $related_str;
global $_ul_left_margin, $_ul_margin, $_list_pad_str;
$links = links_get_related_db($vars['page']);
if ($tag) {
ksort($links);
} else {
arsort($links);
}
$_links = array();
foreach ($links as $page=>$lastmod) {
if (check_non_list($page)) continue;
$r_page = rawurlencode($page);
$s_page = htmlspecialchars($page);
$passage = get_passage($lastmod);
$_links[] = $tag ?
'<a href="' . $script . '?' . $r_page . '" title="' .
$s_page . ' ' . $passage . '">' . $s_page . '</a>' :
'<a href="' . $script . '?' . $r_page . '">' .
$s_page . '</a>' . $passage;
}
if (empty($_links)) return ''; // Nothing
if ($tag == 'p') { // From the line-head
$margin = $_ul_left_margin + $_ul_margin;
$style = sprintf($_list_pad_str, 1, $margin, $margin);
$retval = "\n" . '<ul' . $style . '>' . "\n" .
'<li>' . join($rule_related_str, $_links) . '</li>' . "\n" .
'</ul>' . "\n";
} else if ($tag) {
$retval = join($rule_related_str, $_links);
} else {
$retval = join($related_str, $_links);
}
return $retval;
}
?>
PukiWikiのpluginディレクトリにbacklinks.inc.phpという名前で置いて、PukiWikiでページ編集するときに #backlinksと書けば動作するはずです。PukiWikiのコード(make_related関数)をそのままパクッてるんで、ライセンスはGPLです。こんなんで良ければご自由にどうぞ。
会社の挨拶運動に参加しました。寒空の下30分間、会社の入り口で「おはようございまーす」を連呼しました。
寒さを考慮してほっかいろを配ってくれたので早速使ってみたのですが、最近の製品は発熱量が少ないみたいです。かいろが暖かくなるどころか逆に寒さに負けて冷たくなってくる始末。低温火傷に配慮したのかなあ?それにしてはやりすぎだよなあ?
ちょっと前にニコニコ動画で大流行していた「チーターマン」という伝説級のクソゲーがあるんですが、これを越える超絶クソゲーがあります。
「未来神話ジャーヴァス」というファミコンのゲームなのですが、アクションRPGにも関わらず、説明なくゲームが始まって当然、てな作り方です。ターゲット層と思われる小学生に理解させる気ゼロです。
バッテリーバックアップカセット、クエストシステム、城攻めなどの斬新な要素(当時)も見られます。しかし基本が即死というバランスの悪さ、説明不足すぎて理解不能なクエストなどマイナス点が多すぎです。これは常人にはクリア不可能だと思われます。
ニコニコにクリアムービー(かなり省略されてます)が載ってたので、暇で仕方ない人は探してみてください。見ていても何してるのか全然わからんのが難点だけど…。
今日は飲み物を買いに行ったりしたくらいなので、昨日の晩〜深夜にかけて、友達とゲームしてた話でも。
PS3のありあまるパワーを生かして、ハイビジョン画質(1080p出力)をでかい画面(50インチのプラズマ)に繋いで、ガンダム無双やってました。ポリゴンのアラが見えてしまうくらい、綺麗だなあ。
Wiiでパワプロもやりました。リモコンを振って投げる/打つってのが楽しいです。最初はシンプルすぎる操作を見て、プレイヤーを馬鹿にしてると思ったんですが、やってみると逆にシンプルさが楽しいです。
ただ、PS3やった後にWiiの絵をみると、ぼやけているというかなんというか…。やるなら逆の順番にしたほうが良さそう。
友人の誘いに乗って、京都の三嶋亭にすき焼きを食べに行きました。店の雰囲気に対して、ジーパン+トレーナーという僕らの服装が激しく場違いでした。あやうく周囲の視線で針のむしろになるところでした。個室で良かったと思います。
一食で一ヶ月の食費の半分くらいが吹っ飛びました。しかし…、うまかった…!
食事を食べた後は京都の町をぶらぶら。京都のコンビニはみんな地味な色にしていて面白いです。街並みとの調和ってやつでしょうか。
近くの八坂神社にお参りしました。門の修復工事が終わっていたので、写真を撮りました。柱の朱が鮮やかです。今はまだ直したてで綺麗すぎるきらいがありますけどしばらくしたら良い味が出るでしょう。
神社にお参りしてお土産買った後は、パフェを食いました。男五人でな…、なんか最近こんなのばっかりだw
会社からの帰り道、電車の到着時刻を知らせる電光掲示板を見るとなんかおかしい。先に来るはずの8分が、16分の電車の下に表示されています。普通は到着時刻順に並ぶはずです。
そのまましばらく電光掲示板を見ていると、JR西日本恒例の赤い文字(電車の遅れ時間を示す)が。またですか、もう勘弁してください。
ああ、これはだめだって思ってたら「8分の普通電車は16分より後になる」ってアナウンスが入りました。電光掲示板の順番が入れ替わってる=先行(8分の電車)は来ませんよ、って予告なんですねっ…て、わかりづらいよ。
最終的には10分遅れになって、時間順で正しい順番になりました。結局ホームで20分も待っちゃったYO!遅れの原因は、小動物を跳ね飛ばしたせいらしいです。へぇー。
目次: C言語とlibc
突然printfの動きがおかしくなって、引数で与えた数値を表示したりしなかったりするようになりました。
で、調べてみるとこーんなプログラムになってたわけです。
#include <stdio.h>
int main(int argc, char *argv[])
{
long long int a;
int b, c;
a = 0x1234567887654321LL;
b = 200;
c = 300;
printf("a:%d, %s, b:%d, c:%d \n", a, "strings", b, c);
return 0;
}
実行してみると
$ gcc a.c $ ./a.out Segmentation fault
見事に落ちました。
このプログラムのまずいところは変数aは8バイト(long long int型)あるのに、printfには %d書式(signed int型の指定)と指示しているため、printf側が4バイトしか見ない、ってところです。残った4バイトは次の %s指令のデータと見なされて、その結果変なアドレスを見に行ってプロセスが死にます。
なので、この場合は %dじゃなくて %lldと書いてlong long signed int型であることを指定すべきです。正しく動いたときの結果はこんな感じ。
$ ./a.out a:1311768467139281697, strings, b:200, c:300
整数だからといってなんでもかんでも %dにしちゃだめですよ、って教訓ですな。
$ gcc --version gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gcc -Wall a.c a.c: In function 'main': a.c:12: warning: format '%d' expects type 'int', but argument 2 has type 'long long int'
ちなみにgccなら -Wallオプションを指定すれば、printfの書式指定が間違っていたときに教えてくれます。
もちろん好きこのんでこんな状態を作ったわけではありませんので、お間違いなく…。
この問題に出会うきっかけとなったプログラムは、言うなれば「typedef地獄」でしょうか。ぱっと見ても、整数なのか浮動小数点数なのか、はたまた構造体なのか…型が全くわかりません。何よりひどいのはtypedefが連鎖しまくっていることでしょうか。
例えばAライブラリのA_TypeがBライブラリのB_Typeのエイリアスだったとして、そのB_TypeがさらにCライブラリのC_Typeのエイリアスで、それがさらにDの…というように、ひねりのないtypedefが延々と続きます。
そのくせ最後まで辿ってみると無条件でtypedef int X_Type;(単なるint)とかいうオチが多いので、ウザいことこの上ない。
やがて調べるのが面倒くさくなって、どうせlongかintだろって思ってなめてたら、long long intのエイリアスがいくつか混ざっていて、警告オプション -Wallもご丁寧に抹消されており、上記の問題にはまったわけです。
C言語において、ダメなマクロの話は良く聞きますが、ダメなtypedefの使い方はそうそうないと思う。
大好きな蒟蒻畑をダイエーで3袋くらい買ってきてもさもさ食ってたら、一瞬でなくなりました。しかも食べ過ぎて具合悪くなってきたし…。
それはさておき、蒟蒻畑の袋に「高齢者と子供は食べないで」というイラストが入っていることに気づきました。以前は裏側に「気をつけて食べて」とか「スプーンで食べて」という注意書きがあっただけだった気がします。
袋の表にしっかり描いてありますね。右下のマークの部分を拡大すると、以下のような具合です。
食べるな、とはっきり描いてあります。喉に詰まらせる事故が起きる度にこの手の警告は厳しくなりますが、ついに注意や警告ではなくて禁止になってしまったようです。事故が起きまくる交差点が一時停止 -> 信号 -> 歩車分離へと進化する(?)のと似たような物か…。
Javaでプログラムしていたら妙な現象に気づきました。
以上の処理を行うループを回していると、PCの時計が3倍くらいの速さでどんどん進んでしまいます。バッファに何も描かずにdrawImageするであるとか、20ms以上の時間をsleepに指定した場合には、問題ないようです。
バッファに描いてdrawImageしてsleepを呼んで待つ、というパターンはゲームでありがちな処理だけに困ってしまいます。何が悪いのかさっぱりわからない。Javaとその内部に詳しい人が居たら、何が起きてるのか教えて欲しいところです。
それともなんだ、地球のためにCPUパワーを食うBlitではなくFlipにしなさいっておぼしめしなのか…?
検証に使ったコードは以下の通りです。
import java.applet.*;
import java.awt.*;
public class TestClockSkew extends Applet implements Runnable {
Image i;
public void init() {
i = this.createImage(800, 600);
Thread t = new Thread(this);
t.start();
}
public void run() {
while (true) {
Graphics g = i.getGraphics();
g.setColor(new Color(0, 0, 0));
g.fillRect(0, 0, 500, 500);
g.dispose();
this.getGraphics().drawImage(i, 0, 0, null);
try {
Thread.sleep(11);
} catch (InterruptedException e) {
}
}
}
}
当初は実際に動作するアプレットを貼りつける予定でした。しかし実行したところで、黒い画面が出るだけで何も面白くないうえに、もし皆さんのマシンの時計が狂ったりしたら大迷惑なのでやめました。
< | 2008 | > | ||||
<< | < | 02 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | - |
合計:
本日: