2008-02-22

Customizing on ASUS Launcher the EeePC's WM easy mode

apt-getでウィンドウマネージャを追加すると自由にカスタマイズが可能です、では面白くないどころか、折角の軽快さが失われてしまいます。そこで、必要最低限の修正で利便性の向上を図ってみます。とか何とか言ってここのパクリです。

まずFile Managerからターミナルの起動がウザくて仕方ないです。これはCtrl+Alt+Tでショートカット可能。個人的にはこれで十分ですが、

Easy Modeにスタートメニューをくっ付ける。

  1. ターミナル上げる。

  2. > mkdir /home/user/.icewm

  3. > cp /etc/X11/icewm/preferences /home/user/.icewm/

  4. .icewm/preferencesのTaskBarShowStartMenuを0から1に変更。

  5. X Windowを再起動します。

  6. Ctrl+Alt+BSでスタートメニューが現れます。


あとは適当に設定を編集してメニューをカスタマイズします。

2008-02-19

Localization on Eee PC

ASUS Eee PC
この手の超軽量ノートはガジェット好きのギーク魂をくすぐるものの、ほとんどの場合において中途半端な完成度で飽きてしまうのですが、それでもついウッカリと手を出さずに居れないのもまた事実。中文版の黒を入手したのでl10nの覚書を交えて簡単にレビュー。

まずこのサイズのノートにしては満足のいく鍵打感、かつASCII配列。もうこの時点で、私個人の費用対効果は合格点だと言えます。かつて過ぎ去っていったガジェット達も、多くがこの辺りに敗因がありますので。

ゼロスピンドルかつ小型。いやMacBookAirは当然あこがれるけど、あまり大きなバッグを持たない私にとっては薄さより小ささ、軽さが重要。これまた合格点。

ちなみに国内版はJIS配列かつWindows搭載というF**kin' shitな仕様ですが、それが嬉しい人にとってはまたやはりプラスですね。ヨドバシの店頭で触った限りで言えば、わりと軽快に動作していました。メモリは換装されていない状態です。

では中文版Xandrosの日本語化の流れ。実態はDebian Linuxに皮被せたような代物ですから、問題は読めない漢字の海の中からターミナルを起動する事、その一点だと言えるでしょう。正直に申せば、先人のまとめを見るまで分かりませんでした。GRUBでスタンドアロンに入ろうかと思ったくらい。なのでほとんどここを参照。


  1. 左から二つ目のタブを選択し、なんとか管理員と書かれたアイコンをクリック。

  2. FileManagerが起動するので、Ctrl-Tでターミナルを起動。

  3. > sudo su -

  4. > cd /etc/apt; vi sources.list

  5. deb http://ftp.jp.debian.org/debian/ etch main contrib non-free を append し保存。

  6. > apt-get update

  7. > apt-get install ttf-vlgothic いやまぁフォントはお好きなのをどうぞ。

  8. > dpkg-reconfigure locales

  9. メニューで ja_JP.EUC-JP EUC-JP, ja_JP.UTF-8 UTF-8 を選択。

  10. > apt-get install emacs

  11. > apt-get install ddskk scim-skk

  12. 再起動後は Ctrl-SPC で日本語入力が可能です。



他にも色々と入れたいところですが、容量は割と小さいので目的を絞っておくことを忘れないで下さい。ちなみに私は gcc, ghc6, swi-prolog, latex を入れたわけですが。

備忘録代わりに Emacs の haskell-mode の設定について。まずここからファイルを wget か何かして来て、適当に展開。設定ファイル .emacs に以下を追記。

(load "~/haskell-mode-2.4/haskell-site-file")
(setq load-path (cons "~/haskell-mode-2.4" load-path))
(setq auto-mode-alist
(append auto-mode-alist
'(("\\.[hg]s$" . haskell-mode)
("\\.hi$" . haskell-mode)
("\\.l[hg]s$" . literate-haskell-mode))))
(autoload 'haskell-mode "haskell-mode"
"Major mode for editing Haskell scripts." t)
(autoload 'literate-haskell-mode "haskell-mode"
"Major mode for editing literate Haskell scripts." t)
(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
(add-hook 'haskell-mode-hook 'turn-on-haskell-ghci)
(setq haskell-literate-default 'latex)
(setq haskell-doc-idle-delay 0)


そのままでも非常によく出来たモードなのですが、以下のように手を入れます。これらの修正はここを参照です。

-- haskell-site-file.el
+ (autoload 'inferior-haskell-load-and-run "inf-haskell" "\
+ Pass the current buffer's file to the inferior haskell process.
+ If prefix arg \\[universal-argument] is given, just reload the previous file.
+
+ \(fn &optional RELOAD)" t nil)
(autoload 'inferior-haskell-type "inf-haskell" "\

-- haskell-mode.el
- (define-key map [?\C-c ?\C-l] 'inferior-haskell-load-file)
+ (define-key map [?\C-c ?\C-l] inferior-haskell-load-and-run)


このモードを使い始めた時に思う勘違いにインデントがありますが、これはTABを押すごとに候補となるインデントをローテートします。是非たぶたぶしてやって下さい。

あとコンパイルエラー時のカーソルの飛び先をカレントウィンドウにする場合は、こちらを参照して haskell-ghci-gen-load-file を次のように書き換えます。


-- haskell-ghci.el
(defun haskell-ghci-gen-load-file (cmd cd)
(save-excursion (haskell-ghci-go cmd cd))
(let ((haskell-file-buffer (current-buffer)))
(pop-to-buffer haskell-ghci-process-buffer)
(goto-char haskell-ghci-load-end)
(if (re-search-forward
"^Ok, modules loaded" nil t)
(progn (goto-char (point-max))
(recenter 2)
(message "There were no errors.")
(pop-to-buffer haskell-file-buffer))
(goto-char haskell-ghci-load-end)
(haskell-ghci-locate-next-error))))

2007-11-10

setitimer on leopard

POSIX系OSでプロファイラなどを作る際にsetitimer関数を利用します。以下のようにするとタイマを設定することが出来ます。

struct itimer value, ovalue;

value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 1;
value.it_value.tv_sec = 0;
value.it_value.tv_usec = 1;
if (setitimer(ITIMER_PROF, &value, &ovalue) != 0)
{ error_code; }

ここで設定した秒数ごとにSIGPROFシグナルが投げられますので、プロファイラをsigactionでSIGPROFに設定しておきます。

struct sigaction old;
struct sigaction new;

memset(&new, 0, sizeof(new));
new.sa_handler = プロファイラ関数;
if (sigaction(SIGPROF, &new, &old) != 0)
{ error_code; }

ところでプロファイラを起動する間隔ですが、これは先ほど設定したSIGPROFを投げるインターバルに依存しますから、上の例のように気軽に1マイクロ秒とかには出来ないわけです。基本的には。でもLinuxなどでは適当な値に丸められるので、上記のようなコードが放置されるケースが見受けられます。

さて先頃リリースされたLeopardにコレといった不具合も出てないようだったので喜んでインストールした私です。そして色々とソフト入れてて上の問題にぶつかったわけです(SWI-Prologでしたが)。なんとLeopardは1マイクロ秒でもタイマが起動しちゃようです、ビビりました。そんな間隔で起動されたら他のプロセスにちっともスイッチされなくなります。そういうわけなので統計クロックから適切な値を設定してやるようにしましょう。

value.it_interval.tv_usec = 1000000/(int)sysconf(_SC_CLK_TCK);

2007-11-06

Prolog (6)

なんかunfoldの定義を少し間違って記憶してたように思います。Haskellでリスト用の定義を見るとこんな感じ。

unfold p f g x =
if p x
then []
else f x : unfold p f g (g x)

Prologでは前回示したようにunfoldの外のゴールでバックトラック制御を行えますから、終了判定は要らないですね。アレはアレで使い道はあるのでunfold2とかにリネームしておいて、リスト用unfoldlを正しく書くとこんな感じですかね?

% unfoldl/5
unfoldl(Fn1, _, X, L, L1) :-
G =.. [Fn1, X, Y],
call(G),
append(L, Y, L1).
unfoldl(Fn1, Fn2, X, L, L2) :-
unfoldl(Fn1, Fn2, X, L, L1),
G =.. [Fn2, X, Y],
call(G),
unfoldl(Fn1, Fn2, Y, L1, L2).

% make_list/2
make_list(X, [X]).

?- unfoldl(make_list, inc, 1, [], L), length(L, 100), foldl(plus, 0, L, Sum).
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
Sum = 5050

ただHaskellだと型システムのチェックが働く部分や、カリー化された関数が書き易い部分が組み合わさって強力なfold/unfoldですが、Prologだとその辺りでメリットが無いので正直なところ使い勝手は微妙です。

ところで最近都内でProlog勉強会をやっています。ご興味をお持ちの方が居られましたら是非ご一報を。隔週で長期的にやっております。
次回開催概要
場所: 中目黒GTタワー
日時: 11/10(Sat) 14:00-
内容: Prologへの入門 4-5章
連絡: hiro.kosh@gmail.com

2007-11-04

Prolog (5)

前回に引き続きリスト系のユーティリティ述語の紹介です。

fold(l/r)を定義したら当然のことですがunfoldが定義したくなりますね?幸いにもPrologはバックトラックがありますから、特に遅延評価のための仕組みを用意せずとも、Haskellのようにunfoldを書くことが出来ます。しかしその前にもっと細かいユーティリティを定義しておきます。

まずはリストの最後の要素を取得するlast/2です。

% last/2
last([X], X).
last([_|R], X) :- last(R, X).

?- last([1, 2, 3], X).
X = 3


続いてリストの最後以外の部分を取得するunlast/2です。

% unlast/2
unlast(L, R) :-
last(L, Y),
append(R, [Y], L).

?- unlast([1, 2, 3], L).
L = [1, 2]

個人的にはこの述語なんか簡単で、如何にも宣言的な書き方かなぁと思っています。二つ目のゴールで最後の要素を後ろに付けたリストが元のリストだと宣言してるわけですね。

さてリストのN番目の要素を取得するnth/3はこんな感じ。

% nth/3
nth(1, [X|_], X).
nth(N, [_|R], X) :- N > 1, N1 is N - 1, nth(N1, R, X).

?- nth([1, 2, 3], 2, X).
X = 2


ところで引数の並びをどうするかというのは悩みどころです。特に高階述語を書く場合は、与える引数の位置が重要ですからね。そこで自分の中でルールを決めておくという手もあるのですが、順番を変えたい場合はチェインというのを定義してやります。

% last1/2
last1(X, L) :- last(L, X).

上のlast1/2ではlastを呼び出すことしかしません。ただし引数を並び替えています。このようにエイリアスのような役目をする述語を(慣用的に)チェインと呼びます。

それではunfold/4を定義してみましょう。

% unfold/4
unfold(Fn, X, L, L1) :-
last(L, Y),
G =.. [Fn, X, Y, Y1],
call(G),
append(L, [Y1], L1).
unfold(Fn, X, L, L2) :-
last(L, Y),
unfold(Fn, X, L, L1),
unfold(Fn, Y, L1, L2).

?- nth(10, L, X), unfold(plus, 0, [1], L).
L = [1, 1, 2, 3, 5, 8, 13, 21, 34|...],
X = 55

出来ました。ちなみにnth/3を使っている理由はもうすでにお気づきですね?それではunfold/4単体でフィボナッチ数を計算してみましょう。

?- unfold(plus, 0, [1], L).
L = [1, 1] ;
L = [1, 1, 2] ;
L = [1, 1, 2, 3] ;
L = [1, 1, 2, 3, 5] ;
...

ご覧の様に、別の解を要求する度にリストが伸びて計算を行っていきます。上の例ではnth/3でリストの幾つ目の要素が欲しいのかを条件として与えていますから、それを満たすリスト長になるまでバックトラックを起こして次の値を計算しているわけです。

2007-11-01

Prolog (4)

Prologは高級言語に属すると思うのですが、昨今のプログラミング言語を見るとLLは言うに及ばずc++でもSTLという便利なライブラリが付いてきます。最もそういったユーティリティはPrologでは大体が簡単に作れるものなので、マイライブラリを構築している人が大半かと思われます。とりあえず定番どころからそういったものを晒して行く事にします。

リストオブジェクトが使えるとプログラマの本能は、要素に対する関係を記述してやりたくなります。まずは個々の要素と関係を満足する要素のリストを作るmapです。

% map/3
map(_, [], []).
map(Fn, [X|Xs], [Y|Ys]) :-
G =.. [Fn, X, Y],
call(G),
map(Fn, Xs, Ys).
% inc/2
inc(X, Y) :- Y is X + 1.

?- map(inc, [1,2,3], L).
L = [2,3,4]


続いて関係を満足した要素だけからなるリストを作るfilterです。

% filter/3
filter(_, [], []).
filter(Pr, [X|Xs], [X|Ys]) :-
G =.. [Pr, X],
call(G),
filter(Pr, Xs, Ys).
filter(Pr, [_|Xs], Ys) :-
filter(Pr, Xs, Ys).

?- filter(number, [a,1,b,2,3,4], L).
L = [1,2,3,4]


さらに一般的な高階関数fold(l/r)はこんな感じです。

% foldl/3
foldl(_, X, [], X).
foldl(Fn, Y1, [X|Xs], Y) :-
G =.. [Fn, Y1, X, Y2],
call(G),
foldl(Fn, Y2, Xs, Y).

?- foldl(plus, 0, [1,2,3,4], Sum).
Sum = 10

% foldr/3
foldr(_, X, [], X).
foldr(Fn, Y1, [X|Xs], Y) :-
foldr(Fn, Y1, Xs, Y2),
G =.. [Fn, X, Y2, Y],
call(G).
% minus/3
minus(X, Y, Z) :- plus(Z, Y, X).

?- foldr(minus, 0, [1,2,3,4], Q).
Q = -2


ところで上で出てきたオペレータに入門書では見慣れないものがありますね。=..って奴です。コイツは複合項(Compound TermあるいはStructureとも呼ぶ)を作成する演算子(正確には(=..)/2で自由変数とリストが引数)です。call/1は引数として渡されたゴールを実行しますので、それを用意しているわけです。

G =.. [Fn, X, Y].
G = Fn(X, Y)

処理系によっては次のようにしてcallを使えるものもあります。

call(Fn, X, Y). % Fn(X, Y) to be executed.