Archive for 10月, 2009

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

(subtypep '(array (unsigned-byte 8) (*)) '(array t (*)))
;=> NIL

この場合は、(array t (*))ではなく、(array * (*))を使うのが正しいようです。