特定の日(2008-01-20)のブログエントリーに大量にスパムコメントが来る。よくわからないので移動。

Software Design 2008/01 Emacs 特集

なかなか良い。elispjava との比較は苦しいが。

ところで、最近入れた emacs 22.1.1 の環境では、 emacs の組み込み関数でも describe-function で参照すると、
C のコードが参照できるらしい。
以下は elisp の関数 atom と listp の部分。elisp の 組み込み関数はこんな感じのようだ。上記の特集と組み合わせると Emacs を読み解けるかもしれない(時間が欲しい)。

DEFUN ("listp", Flistp, Slistp, 1, 1, 0,
       doc: /* Return t if OBJECT is a list, that is, a cons cell or nil.
Otherwise, return nil.  */)
     (object)
     Lisp_Object object;
{
  if (CONSP (object) || NILP (object))
    return Qt;
  return Qnil;
}

以下も参考になる。

ライフゲーム

dokaku.org のお題より。(投稿したけどログインし忘れてた、、)
Common Lisp (CLOS) で書いてみた。

感想として。ライフゲームという小さい宇宙、実装してみるとなかなか楽しかった。
以下は実はどう書くに投稿するにはいろいろと格好悪いコードである。
特に個人的には配列を処理するようなコードが不慣れで下手。

昔から、何故かライフゲームは隅から順番に更新していくと思い込んでいて、
「更新する順番によって結果がかわるのではないか?」と疑問に思っていた。
実際は、次の盤の状態の計算結果を一時的に変数に格納して、
その後全体を更新する、という2ステップがあるのだった。
やはり手は動かしてみるものだ。

(defclass board ()
  ((width :accessor board-width :initarg :w)
   (height :accessor board-height :initarg :h)
   (cells :accessor board-cells :initarg :cells)))

(defmethod print-object ((board board) stream)
  (print-unreadable-object (board stream)
    (format stream "board~%")
    (loop for y from 0 below (board-height board)
	do
	  (loop for x from 0 below (board-width board)
	      do
		(format stream "~a" (if (cell board x y) "X" ".")))
	  (format stream "~%"))))

(defun make-board (w h)
  "constructor"
  (make-instance 'board :w w :h h :cells (make-array (list w h) :initial-element nil)))

(defun make-random-board (w h)
  (let ((board (make-board w h)))
    (loop for y from 0 below (board-height board)
	do
	  (loop for x from 0 below (board-width board)
	      do
		(setf (cell board x y) (< (random 10) 3))))
    board))

(defmethod cell ((board board) x y)
  "accessor"
  (aref (board-cells board) (mod x (board-width board)) (mod y (board-height board))))

;; (setf (cell board x y) value) 
(defsetf cell (board x y) (value)
  `(setf (aref (board-cells ,board) (mod ,x (board-width ,board))
	       (mod ,y (board-height ,board))) ,value))

(defmethod cell-neighbours ((board board) x y)
  (list (cell board (1- x) (1- y))
	(cell board x (1- y))
	(cell board (1+ x) (1- y))
	(cell board (1- x) y)
	(cell board (1+ x) y)
	(cell board (1- x) (1+ y))
	(cell board x (1+ y))
	(cell board (1+ x) (1+ y))))

(defmethod cell-survivep ((board board) x y)
  (let ((c (cell board x y))
	(n (count-if #'identity (cell-neighbours board x y))))
    (cond
     ((and (not c) (= n 3)) t) ;; born
     ((and c (or (= n 3) (= n 2))) t) ;; keep
     (t nil)))) ;; die

(defmethod update ((board board))
  (let ((next
	 (loop for y from 0 below (board-height board)
	     append
	       (loop for x from 0 below (board-width board)
		   collect (list x y (cell-survivep board x y))))))
    (loop for elt in next
	do
	  (destructuring-bind (x y v) elt
	    (setf (cell board x y) v))))
  board)