マンガで分かるLisp [Section 3.1]
1月 20th, 2010今年1年を振り返る
12月 31st, 2009適当に今年の出来事を10個集めてみました。
ポケステでLispが動いた
去年の年末から今年の年始にかけてポケステ向けのLispインタプリタを作りました。
フルマラソン走った
翌日の筋肉痛が凄かったです。タイムが遅かったのが残念。
Mac Book買った
非常に使いやすいです。いい買い物をした。
自転車で琵琶湖一周
大体時速20kmをキープし続けることができました。次走るときはもう少し良い自転車で走りたい。
マンガで分かるLispがたくさん
最近停滞気味ですが、最後まで続けたいと思います。
BiwaSchemeでゲーム作った
Schemeでブラウザ向けのゲームが作れるというのは面白いですね。
院試受かった
院試が近い時期に彦根まで自転車でひこねのよいにゃんこのグッツを買いにいったりしましたが、
試験日やその前日にカツ丼やチキンカツ定食を食べたおかげか無事合格できました。
CLでJavaのアセンブラ/逆アセンブラを作った
CLでプログラムを書くのも大分慣れてきたおかげか、比較的楽に書くことができました。
cl-openglで遊んだ
こいうプログラムを書くのは楽しいですね。
今年1年振り返ってみたけど、ろくなことをやってない
特に書くことがなかったので再帰的なリンクを張っておきます。
Prologでオシオキ
12月 1st, 2009メモリたくさん欲しいです(Yet Another Ranha)
を読んで、私もオシオキしてみることにしました。
画像が小さくて良く見えませんが、4人が水泳大会の順位を言っていて、
そのなかで一人だけ嘘をついているのでその人を見つけ出すみたいです。
(順位も求めるみたいですが、誰が嘘をついているか分かれば順位は自明なので、
順位は表示したりしていません。)
私はranhaさんのように変態紳士では無いので、素直にPrologを使いました。
処理系はSWI-Prolog。
;; 二つの集合が等しいか set_eq([], []). set_eq([X|Xs], Y) :- member(X, Y), delete(Y, X, Z), set_eq(Xs, Z). ;; 4人が別々の順位になるか rank(X,Y,Z,W) :- set_eq([X,Y,Z,W], [1,2,3,4]). ;; それぞれの言い分 ayu(1). ayu(2). suzu(1). suzu(2). naru(N, S) :- N < S. kotori(1). ;; オシオキされる人 oshioki(ayu) :- suzu(S), kotori(K), rank(_,S,N,K), naru(N, S). oshioki(suzu) :- ayu(A), kotori(K), rank(A,S,N,K), naru(N, S). oshioki(naru) :- ayu(A), suzu(S), kotori(K), rank(A,S,_,K). oshioki(kotori):- ayu(A), suzu(S), rank(A,S,N,_), naru(N, S).
で、動かしてみたら、誰をオシオキしたらいいのかすぐに分かります。
?- oshioki(X). X = suzu
SWI-Prologのdeleteの引数が想像と逆ですこしハマりました。
それにしてもあまりきれいじゃないですね。
もう少しうまく書けないものか。
マンガで分かるLisp [その9]
11月 25th, 2009マンガで分かるLisp [Section 2.4]
11月 17th, 2009cl-openglで変なもの作った
10月 13th, 2009ものすごく適当に書いてもそれっぽく動く。cl-opengl凄い。
Common Lispでゲームを作るのは案外簡単な気がしてきた。
背景の写真は滋賀県の某所で撮ったものです。
画面のキャプチャにはCopernicusを使用しました。
ただ、Mac Bookのスペックの問題か、秒間2フレームほどでしか撮影できなかったので、
cl-openglのプログラムの方をゆっくり動かし、撮影した動画をiMovieで早送りしました。
早めのreturn
10月 10th, 2009例えば、C言語で
int foo()
{
int ret;
if (bar()) {
/* (行数的に)短い処理 */
ret = 1;
}
else {
/* (行数的に)長い処理 */
ret = 0;
}
return ret;
}
こんな風な書き方をする人と、
int foo()
{
if (bar()) {
/* 短い処理 */
return 1;
}
/* 長い処理 */
return 0;
}
こんな風な書き方をする人、どちらが多いんでしょうか。
私は早めにreturnで関数を抜ける方が読み易いし、
長い処理のネストが一段浅くなるので、後者の方を好んで使いますが、
一部業界では「関数にreturnは1個しか書けない」という謎の規約があるため、
前者のような書き方を強要されるそうです。
Common Lispでも同様に
(defun foo ()
(cond ((bar)
;短い処理
1)
(t
;長い処理
0)));
のような書き方をするか、
(defun foo ()
(when (bar)
;短い処理
(return-from foo 1))
;長い処理
0)
のような書き方をするか選べます。私はこれも後者を好んで使います。
けど、Lispの入門書ではこのようにreturn-fromを使ってるのをあまり見ない気がします。
Schemeだとreturnがないのでcall/ccを使うことになります。
(define (foo)
(call/cc
(lambda (ret)
(if (bar)
(begin
;短い処理
(ret 1)))
;長い処理
0)))
ただ、この書き方だと結局ネストが深くなってしまうので、
引数として継続を受け取った方が自然かもしれません。
(define (foo ret)
(if (bar)
(begin
;短い処理
(ret 1)))
;長い処理
0)
(call/cc foo)
Schemeのcall/ccを利用した早めのreturnも好きなんですが、
その目的のためだけにcall/ccはちょっと重たいかもしれません。
脱出専用なので、処理系がどうにかして効率のいい実行をしてくれないのかな。
cl-openglとかarrayの型とか
10月 8th, 2009*cl-opengl*
OpenGLのことなんて何も知らないけど、
適当にcl-openglを弄ったらなんだか3Dっぽくなった。


静止画像じゃ分かりにくいですが、回転します。
あと、回転すると、表示の前後関係が狂います(笑)
*arrayの型*
以前のエントリで
「本当は (array (unsigned-byte 8) (*))を指定した方がいいけど、
リーダマクロ #( で作った配列を扱いたいから、 (array t (*)) を指定しました」
みたいなことを書いたんですが、思いっきり間違ってました。
(array t (*))は任意のオブジェクトを保持できる一次元配列で、
(array (unsigned-byte 8) (*))のような、要素の方が制限された配列を含みません。
(subtypep '(array (unsigned-byte 8) (*)) '(array t (*))) ;=> NIL
この場合は、(array t (*))ではなく、(array * (*))を使うのが正しいようです。




