Archive for the ‘プログラミング’ Category

VC++2008でECLのmake

金曜日, 10月 3rd, 2008

ページの最後の方にmakeの一連の流れを書いてあります。
さっさとWindowsへのECLの入れ方を見たい人はそちらをどうぞ。

WindowsのDLLをCLを使って書きたいため、
CのソースにCLのソースを埋め込もうと思い、
ECLを試してみることにしました。
HDDをあさってみたら、以前ダウンロードした「ecl-0.9j.tgz」というファイルがあったので(*)
まずそれを展開。若干古そうな気がしたのでcvs updateをかけておきました。
cygwin上でmakeしようとしたんですが、上手くいかなかったので放置していたという恥ずかしいものです(笑)
そして、Visual C++ 2008 Express Editionをダウンロード。
しかし、「Visual Studio 2008 コマンドライン」(*)を起動しようとすると、
「使い方が間違っています」
という悲しいエラーが出てきました。
環境変数を設定するバッチファイル(vsvars32.bat)を覗いてみると、
怪しげな命令があったので、適当に書き直したらちゃんと動きました。
Microsoftどうなってるんだ… Vista用の命令?
(※)インクルードパスなどの環境変数を設定してコマンドラインを立ち上げるもの
それで、ECLのマニュアルに従い、nmakeすると、何故かエラーが発生。
場当たり的に修正しながら突き進んでみたものの、途中で完全に行き詰まりました。
ここで、一旦諦めかけたんですが、もしかしてと思い、
ecl-9.0j.tgzを展開しなおして、cvs updateなど余計なことをせずにmakeしてみると成功。
なんとも悲しいオチが待っていました。
SourceForgeの方に新しいバージョンのアーカイブが無いか確認しに行くと、
ecl-0.9l.tgzというものがあったので、これをダウンロードしてmake。一発で成功しました。
恐らくこっちの方が新しいと思うのでこれを使うことに。

> ecl
ECL (Embeddable Common-Lisp) 0.9i (CVS 2008-06-19 17:09)
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2000 Juan J. Garcia-Ripoll
ECL is free software, and you are welcome to redistribute it
under certain conditions; see file 'Copyright' for details.
Type :h for Help.  Top level.
> (car '(a b c))
A
>

疲れたので今日はここまで。
起動時に「0.9i」と出てるのが少々気になるけど、あえて気にしないことに。

* Windows XP上でのECLのmake方法まとめ *
1. Visual C++ 2008 Express Editionをダウンロード及びインストール
2. C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.batを以下のように変更

* 変更前 *
call :GetWindowsSdkDir
if not "%WindowsSdkDir%" == "" (
set "PATH=%WindowsSdkDir%bin;%PATH%"
set "INCLUDE=%WindowsSdkDir%include;%INCLUDE%"
set "LIB=%WindowsSdkDir%lib;%LIB%"
)
* 変更後 *
rem call :GetWindowsSdkDir
set WindowsSdkDir=C:\Program Files\Microsoft SDKs\Windows\v6.0A\
rem if not "%WindowsSdkDir%" == "" (
set "PATH=%WindowsSdkDir%bin;%PATH%"
set "INCLUDE=%WindowsSdkDir%include;%INCLUDE%"
set "LIB=%WindowsSdkDir%lib;%LIB%"
rem )

3. ECLのアーカイブをダウンロード及び展開
4. スタートメニューから「Visual Studio 2008 コマンドライン」を起動。以下のコマンドを入力

cd (ECLの展開先)\msvc
nmak
nmake install prefix=(インストール先(ディレクトリは勝手には作られません))

当然のことながらファイルパス等は適宜修正してください。
自分のPCでしか試していないので、他のWindows XP環境で上手くいくかは不明です。
というか、VC++のバッチファイルは普通に考えたら触らなくてよさそうなんだけど…

Lispで演算子順位構文解析

水曜日, 10月 1st, 2008

夏休みが終わってしまいました。
そして同時に前期の成績が発表されました。
春先に「単位が足りなくい」という恐ろしくリアルな夢を見ましたが、
どうやら無事に4年生に進むことは出来そうです(4年で卒業出来るかはまだ分かりません(笑))。

という訳で(?)Lispで演算子順位構文解析を行うプログラムを書きました。
工夫した点はマクロを使って予め優先順位のテーブルをコードに展開したこと。
キャッシュのことを考えたら展開した方が遅いかもしれませんが、それは気にしない方針で。
あと、手を抜いた点はストリームからの読み込みはread関数を使ったこと。
演算子に大して何もしないリーダマクロ関数を設定して楽をしてます。
「マイナス」と「引く」を区別できない気もするけど、それも気にしない方針で。

(def-op-parser test-parser (input stack acc)
()
(((#\+ 1 :left) (let ((x (pop acc)) (y (pop acc))) (push `(+ ,y ,x) acc)))
((#\* 2 :left) (let ((x (pop acc)) (y (pop acc))) (push `(* ,y ,x) acc))))
((( #\( #\) ) )))

まず、def-op-parserというマクロを使ってパーサ関数を定義。
第1引数は作成する関数の名前、第2引数は後で使う変数の名前。
第3引数はリテラルに対する操作(今回はなし)。
第4引数は演算子とその優先順位、結合性、還元時の操作。
第5引数は括弧とその還元時の操作(今回はなし)。
そんで、これを使ってみたらこんな感じです。

OP-PARSER> (with-input-from-string (s "(1+2*3+4)*5+6*7")
(test-parser s))
(+ (* (+ (+ 1 (* 2 3)) 4) 5) (* 6 7))

なんか上手くいってるっぽい。やったね。

▲完成したときの心境

で、うかべんまで残り1ヵ月程となってしまいましたが、ネタの方が全然出来てません。
そろそろペースを上げてものを作っていかないと…
この構文解析も里々のパースの為に作ったものです。
それにしても、里々って、Lispの様に括弧を使って関数呼び出し等を行う言語なのに、
算術式において優先順位の為に括弧を使うってどうなんだろう…
半角と全角で区別って言うのは流石にかっこ悪い気がする…

Lispがメモリを食い尽くす

月曜日, 9月 29th, 2008

あるとき、emacs上でSLIMEを動かしながらCLのコードを書いてると、
突然HDDアクセスが多発して、ほとんどフリーズに近い状態になりました。
調べてみたら、Lispプロセスが一人でメモリを500MB以上も使っていました。

図1. メモリを食いつくすLispプロセス
一度プロセスを殺して再起動したら直りましたが、時々同じ現象に遭遇します。
メモリを512MBしか積んでいない私のPCにはこれはかなり致命的なのですが、
たまにしか起こらないので原因がよく分からず非常に困りました。
分かっているのは、この現象が起こると同時にemacsとSLIMEのコネクションが切れるということだけ。
そういや、CLISPは使用するメモリの量をあらかじめ制限できたような出来なかったような…
それができたらどうにかなるかも。…根本的な解決策じゃない気もしますが(笑)

unset-macro-character

火曜日, 9月 23rd, 2008

CLには特定の文字をマクロ文字に昇格(?)させてreaderの動作を変化させる、
set-macro-characterという関数が用意されていますが、
逆にマクロ文字を普通の文字に降格させる関数(unset-macro-characterと命名)がありません。
readtableをいじり回したいお年頃の私にはこれがなかなかつらいです。
で、無いものを嘆いても仕方ないので作ってみました。

(defmacro unset-macro-character (char)
`(set-macro-character ,char
#'(lambda (s c)
(declare (ignore c))
(let ((next1 (peek-char nil s nil (code-char 0) t))
(next2 (peek-char t s nil (code-char 0) t)))
(multiple-value-bind (mc nt)
(get-macro-character next1)
(if (or (char= next1 (code-char 0))
(not (char= next1 next2))
(and mc (not nt)))
(values (intern (string ,char)))
(values
(intern
(format nil "~A~S" (string ,char) (read s nil nil t))))))))
t))

基本方針として、

1. 指定した文字(char)に新たな関数を割り当てる
(その際に、set-macro-characterの第3引数にtを与え、区切り文字でなくす。)
2. その関数は次の文字が
 A. 空白文字の場合、文字charのみからなるシンボルを返す
 B. マクロ文字で区切り文字の場合、Aと同様
 C. 文字の終端の場合、Aと同様
 D. それ以外の場合、文字charと次にreadしたもの(おそらく数かシンボル)をつなげたシンボルを返す

というものです。
面倒だったので、大文字、小文字の区別に付いては特に考えていません。
valuesは戻り値を1つにするために使っています。
(internは値を2つ返しますが、リーダマクロ関数は戻り値の数は0か1と決まっているためです)
(code-char 0)はちょっとまずいかも…
で、動かしてみました。

CL-USER> (let ((*readtable* (copy-readtable)))
(unset-macro-character #\,)
(read-from-string "(a,b, c,(d) ,e)"))
(|A,B,| |C,| (D) |,E|)

なんか知らんけど、上手く動いたぞ。
わーい。

気分はこんな感じ
ただ、あまり考えてないので、ちょっと複雑なものがやってくると、
正しく動作しないかもしれません。
(直後にディスパッチング文字なんかがやってくるとまずいかも…)

T216のquoteについて

火曜日, 9月 23rd, 2008

時の人tazantさんのブログ「Lispのひび」にて最近書かれているquoteについて、
いくつが疑問が溜まってきたのでまとめて書き散らしています。
***全ての始まり***

独自の仕様については、バッククォートもクォートも同じクォートして扱う。
バッククォートはクォートの進化系だから。
リストを作るときも「’」を使い、consの代わりにも、appendの代わりにもなる。
(2008-09-20 マクロ)

「クォートとバッククォートの同一視」をして大丈夫なのかが最大の論点。
私はこれに対しては懐疑的。
CL等の

(defmacro my-search (key)
`(assoc ',key *a-list*))

(defmacro abbrev (shot long)
`(defmacro ,short (&rest args)
`(,',longlame ,@args)))

はどうやって表現するのか気になります。
(2つ目のプログラム片はOn Lisp 16.1節「省略」より)。
***’,foo or ‘(,foo)***

,x = (comma x)です。'(comma foo) = ‘(,foo)となるようになっています。
これはある程度独自な仕様ですから、そこら辺はご了承ください。
***中略***
‘(comma foo)と’,fooの区別は付きませんね。
(2008-09-20 マクロの世界へ)

[疑問1]
‘(comma foo) は結局 ‘(,foo) なのか ‘,foo なのかどっち?
私としては ‘(,foo) に展開されると少々やりにくい気がしますが…
***quoteはcommaが無くても特別?***

基本的に評価基準は一致しています。重大なことに気が付きました。
quoteは「,」をつけない限り、そのままです。次の例でどうでしょうか。
***中略***
よって、'(‘bar baz)というリストを作りたいなら、こうなります。

'('quote (('quote bar) baz))
;=> (quote ((quote quote) (((quote quote) bar) baz)))
;=> (quote (quote (((quote quote) bar) baz)))
;=> (quote (quote ((quote bar) baz)))
;=> (quote ((quote bar) baz))
=> '('bar baz)

(2008-09-20 マクロの世界へ – 2)

shiro 2008/09/21 03:27 ふーむ。クオートされた式中において、
1. (quote quote) は quote に置換
2. (quote comma) は comma に置換
3. (comma expr) は exprを評価して置き換え
4. 置換の結果生成されたquote, commaはその効力を失う
とすれば良いのかな。
(上同記事コメント欄)

[疑問2]
『quoteは「,」をつけない限り、そのまま』とのことですが、
実際には(quote quote) の動作が特別扱いされるんですよね。
(quote ((quote quote) a)) を評価すると (quote a)でしょうか?
***,@的な動作の例が見たい***

commaの仕様は、
* ,@みたいなもの。アトムならそのまま付け加える。
* リストなら外の()を外す。もし付けたいなら,(…)でいい
(2008-09-21 マクロの仕様)

[疑問3]
「もし付けたいなら,(…)でいい」とはどういうことでしょうか。
,(func arg)は関数呼び出しとなってしまうため、
括弧を付けたい、取りたいとは別問題になってしまう気がします。
[疑問4]
古い記事に戻りますが、

(= filter (macro (func arg) '(,func ,arg)))
=> (macro (func arg) '(,func ,arg))
(filter reverse '(1 2 3))
; 内部での状態=> (quote ((comma func) (comma arg)))
; quote評価後=> (reverse '(1 2 3))
; もう一度、マクロの最後を評価=> (3 2 1)
=> (3 2 1)

(2008-09-20 マクロ2)

commaがCLの,@のようにリストの外の()を消してしまうなら、
(quote ((comma func) (comma arg)))

(reverse 1 2 3)
となってしまうのではないでしょうか。
***マクロ引数の展開***

fujita-y 2008/09/21 12:14
もしかして、

(= func (lambda (x) (+ x x))
(= hoge (macro (x) '(x ,(x 1))))
(hoge func)
=> (quote (func ,(func 1)))
=> (quote (func 2))
=> (func 2)

ってことなのかな?

tazant 2008/09/21 13:16
マクロ引数(x)は展開時には評価されずに、
マクロとして再評価すると呼び出し元+引数の環境下で
普通の他の関数などの変数として評価されます。
(2008-09-21 マクロに挑戦! コメント欄)

[疑問5]
マクロ引数xが展開時にコンテキストに関わらず展開されないのであれば、
‘(x ,(x 1))
の最初のxはxというシンボルがそのまま残り、
,(x 1)
は展開時に『xという関数に1を付けて呼び出したもの』の値に置換されると思います。
つまり、
(x 未定義値)
というリストが出来上がるのではないかと。
これがfujita-yさんが仰るように
(quote (func ,(func 1)))
に変形されるのであれば、これは展開時にxが展開されるということではないのでしょうか?

CLのリーダマクロで里々を読む

木曜日, 9月 18th, 2008

うかべんに向けて色々模索中。
私をうかべんに誘って頂いたさとーさん
「里々がLispに近いシンタックスを持つ」
というアドバイスを頂いたので、
Lispと里々の類似点、相違点について話そうかと考えたのですが、
私がだらだらと30分も話してもただ眠くなるだけなので、
何か一つものを作って持っていくことにしました。
里々は

*終了
:えんいー
:なんか懐かしいなそれ

の様な、いかにも文字列の出力が主体のスクリプト言語らしい文法を持っていて、
これだけを見たらLispとは似ても似つかないのですが、
その一方で、変数の代入や条件分岐のシンタックスを見ると、

(set,[変数名],[値])
(if,[条件式],[真の場合に返す文字列],[偽の場合に返す文字列])

とのように、これはまあLispそっくりになっています。
そこで思いついたのが、

1. リーダマクロを書き、里々のスクリプトをS式として読めるようにする
(ちょっとしたパースをするだけだからきっと簡単なはず)
2. 読み込んだS式をCLのプログラムに展開するマクロを書く
(きっと、ちょっとしたマクロで書けると思う。根拠はないけど。)
3. ここまで出来たら、里々のスクリプトをCLのプログラムとしてコンパイルできるぞ!
(そしたら、バイトコード or ネイティブコード or Cのソースコードになる。)
4.きっと楽に書いた割には高速に動作するに違いない!
(特にCのソースコードを吐き出せたらちょと手を加えてDLLにしてSHIORIにできるはず)

という妄想をしてみました。
で、コードを書いてみたところ、それらしく見えるものができました。

#dic01.txt
*終了
:えんいー
:なんか懐かしいなそれ

このプログラムをリードすると、次のように変換されます。

(DEFTALK 終了 :TRUE
(話し手交代)
"えんいー"
(話し手交代)
"なんか懐かしいなそれ")

本当はこれを伺かと通信できる様にdeftalkマクロ展開する必要があるのですが、
今は面倒なので標準出力に文字を出すように展開。

(PUSH
(LAMBDA ()
(FORMAT T "~&~A:~A" "さくら" "えんいー")
(FORMAT T "~&~A:~A" "うにゅう" "なんか懐かしいなそれ"))
(GETHASH '終了 *TALK-TABLE*))

実際に、里々のスクリプトを書いたファイルをコンパイルして、
実行する流れはこんな感じです。

MATSURI> (matsuri-compile-file "dic01.txt")
;; Compiling file /usr/home/zick/dic01.txt ...
;; Wrote file /usr/home/zick/dic01.fas
0 errors, 0 warnings
#P"/usr/home/zick/dic01.fas" ;
NIL ;
NIL
MATSURI> (load "dic01.fas")
;; Loading file dic01.fas ...
;; Loaded file dic01.fas
T
MATSURI> (call-talk '終了)
さくら:えんいー
うにゅう:なんか懐かしいなそれ
NIL

なかなかいい感じに動いています。
しかし、今になってLispと一見似ている括弧を使ったシンタックスが厄介だと気づきました。
括弧の内側から評価されるというのはLispと同じですが、
内側を評価して得られた値を使って外側の括弧をリードし直す
という恐ろしい仕様が里々では使われているそうです。

((今の季節)の味覚)

この式を評価するとき、
まず、内側の (今の季節) が評価され 秋 になりますが、
その次には (秋の味覚) が評価されることになります。
(詳しくはこちらを参照してください)
これは思った以上に手強そうです..

スペシャル関数を作ってみた

月曜日, 9月 1st, 2008

昨日言っていたスペシャル関数を実際に作ってみました。

(defmacro desun (name args &body body)
(let ((a (gensym)))
`(progn
(defparameter ,name #'(lambda ,args ,@body))
(defun ,name (&rest ,a) (apply ,name ,a)))))
(defmacro slet (l-list &body body)
`(let ,(mapcar #'(lambda (x) `(,(car x) #'(lambda ,(cadr x) ,@(cddr x)))) l-list)
,@body))

まずは、スペシャル関数を作る、desun(define special function)と、
fletのスペシャル関数版であるsletを作ります。

(desun =hoge= (n)
(when (> n 0)
(print n)
(=hoge= (1- n))))
(defun foo (n)
(=hoge= n))

スペシャル関数=hoge=と、普通の関数fooを作ります。
関数と変数の両方の名前空間を使うのは少々かっこ悪いですが、どうかお許し下さい。

CL-USER> (foo 3)
3
2
1
NIL
CL-USER > (flet ((=hoge= (x) x)) (foo 3))
3
2
1
NIL
CL-USER > (slet ((=hoge= (x) x)) (foo 3))
3

こりゃダイナミックだ!

CLのスペシャルに秘められた罠(?)

日曜日, 8月 31st, 2008

quoteとかsetqとかifといった特殊な制御に用いるためのシンボルって「special operator」だったんですね。
今までずっとこれらのことを「special form」だと思い込んでいました。
special formはspecial operatorを使った式のことを指すらしいです。
(CLHS Glossaryに詳しく書いてます)
今までなんでこんな勘違いをしてきてそして気づかなかったのか非常に謎です。
私がはじめて読んだCLの本である『ANSI Common Lisp』にもしっかり「特殊オペレータ」と書いてますし、
最近読んでいる『実践Common Lisp』にも「特殊オペレータ」という語が使われています。
見事なまでにスルーしてました。
しかし、よくよく考えてみるとCLtL2にはspecial operatorという語が登場しません。
それどころか、関数やマクロの説明として次のような記法を使っています。

symbol-value symbol [関数]
quote object [特殊形式]

symbol-valueの横に[関数]と書いてあり、実際にそれが関数なんだから、
quoteの横に[特殊形式]と書いてあればquoteは特殊形式(special form)ではないのでしょうか。
と、それっぽい言い訳を考えてみたんですが、

もし最初の要素が表5-1に現れたシンボルのいずれかであれば、
そのリストは特殊形式(special form)と呼ばれる。
(5.1.3 特殊形式)

という風に、式全体のことを特殊形式と呼ぶと明記されてました。
なんてこったい/(^o^)\
しかし、quoteなどのシンボル自体をspecial formと書いてある本を何処かで読んだ気がするので、
色々と探し回ってみました。そしたら、bit1985年4月号にこんな記述を見つけました。

5. 関数とスペシャル・フォーム
MacLispなどのFSUBR関数にあたるものは、Common Lispではスペシャル・フォームと呼ばれる。
しかし、スペシャル・フォームはCommon Lispの意味での関数ではない。
あとで述べるように、関数の引数は必ず評価されるのに対して、スペシャル・フォームの引数の
評価の方法はスペシャル・フォームによって異なる。

(setq)         ; 何もしない
(setq x 1)     ; 変数xに1を代入
(setq x 1 y 1) ; xとyに1と2を代入

は全てsetqという名のスペシャル・フォームであるが、変数に対応する引数は
当然のことながら評価されない。ユーザがsetqという名前の関数を定義していけないという
規則はないが、たとえ定義できてもsetqで始まるリスト・フォームはスペシャル・フォームとして評価され、
関数定義は無視されるはずである。
スペシャルフォームは表3の18個が固定されており(以下略)
(湯淺太一・萩谷昌己, Common Lisp入門 1, bit, Vol. 17, No. 4, 1985)

この説明ではspecial operatorを使った式自体のことをスペシャル・フォームと呼んでいる一方で、
「setqという名のスペシャル・フォーム」の表現が使われています。
また、表3にsetq, ifなどが「スペシャル・フォーム」として挙げられています。
わーい、天下の湯淺先生と萩谷先生がそういったんならいいじゃないかと喜んでいたら、
実はこの連載の翌年の1986年にお2人が書かれた『Common Lisp入門』にて

2. スペシャル・フォーム
次の記号のどれかを第一要素とするリスト。
block macrolet(以下略)
(1.5 評価とフォーム)

special operatorはもはや「記号」としか書かれなくなりました。
他の箇所を読んでも「setqと呼ばれるスペシャルフォーム」みたいな表現は一切ありませんでした。
なんてこったい/(^o^)\
結局、quoteやsetqといったシンボルのことをspecial formというのは単なる間違いだったのか、
それとも昔はそう呼んでいた時期があったのか、非常に気がかりです。
話は変わりますが、Common Lispは、スペシャル変数があるのに、
なんでスペシャル関数がないんだという、どうでもいいことに気づいてしまいました。
ほんと何でないんでしょう。使い道がないからなのか、スペシャル変数で代用できるからなのか…

第14回 慢性的CL勉強会[予習]

金曜日, 8月 29th, 2008

久しぶりにCL勉強会の予習。
今回のお題は「The Common Lisp Cookbook – Functions」だそうです。
今回の資料の内容は大体は知っていることだったので、
細かいところを気にしてみることにしました。
– lambdaの話

  • 関数を返す関数のコードがCommon LispとSchemeでは結構違う
  • 関数型のオブジェクトを作るには特殊形式functionをlambda式に適用する
  • lambdaマクロを使うこともできる

CLtL2によると

car部がlambdaであるリストは関数型ではない。
また、いかなるシンボルも関数型ではない。
しかしながら、関数引数を受け付ける標準Common Lisp関数は
シンボルやそのcarがlambdaであるリストを受け入れ、自動的にそれを関数に強制型変換する。
(2.13 関数)

function fn
もしfnがラムダ式であれば、レキシカルクロージャが返される。
(中略)
function特殊形式の結果は、常にfunction型になること<90>を議決した。
(7.1.1 参照)

とあります。
ここまで読んで疑問に思ったんですが、CLtL2には「lambdaマクロ」の存在が載っていません。
それどころか、funcallの説明において

funcall fn &rest arguments
functionはsymbol型かfunction型のみ許されること<90>を議決した。
ラムダ式は、もはや関数の引数として受け付けられない。
つまり、ラムダ式を陽に引数フォームとして記述する際には、
function特殊形式で囲むか、省略形の#’を前置しなければならない。
(7.3 関数の呼び出し)

なんて書いてます。
そうなると「(funcall (lambda (x) x) 3)」のような式はCLtL2的にはエラーとなるんでしょうか。
一方、CLHSにはしっかりとlambdaマクロのことが書いてありました。

This macro could be implemented by:

(defmacro lambda (&whole form &rest bvl-decls-and-body)
(declare (ignore bvl-decls-and-body))
`#',form)

(Macro LAMBDA )

この定義は分かりやすいですね。
– セルの話

  • シンボルは2つのセルをもつ
    • 値セル(value cell) => シンボルに束縛された値を持つ
    • 関数セル(function cell) => シンボルの(大域)関数束縛の定義を持つ?(*)

(*) function cell – can hold the definition of the symbol’s (global) function binding.
CLtL2で値セルと関数セルの説明を探して見ましたが、見つかりませんでした。
代わりに見つかったのがこんな文章。

シンボルの重要な用途として、プログラムの名前として用いることがある。
処理系作成の上からは、変数の概念を実現するために、シンボルのある種の要素を用いるのが
望ましい場合がしばしばある。symbol-valueおよびsymbol-functionを参照して欲しい。
しかしながら、実現の方法は他にもある。したがって、そうしたありうる要素についてはここでは述べない。
(10章 シンボル)

ちなみに、CLHSの用語集にはvalue cellfunction cellがしっかりと載っていましたが、
Cookbookとほぼ同じ内容で、これといって目新しいことは見つかりませんでした。
– カリー化
あと、最後に載っているカリー化関数が気になりました。
&restがあるから、引数を複数取れるけど、これってcurry化っていえるんでしょうか…
まあ、それは置いておいて、appendを使ってるあたりがLispっぽくて面白かったです。

今日は観鈴ちんがゴールした日なのでGoogle Mapでゲーム作った

木曜日, 8月 14th, 2008

昨日気づいたんですよ。
Google Map APIを使えばゲームが作れるんじゃないかって。
地図の上で車を走らせたり、飛行機を飛ばすといった、
地図と連携したゲームじゃなくてもっと単純なゲームを。

遊ぶ

AIRを知らない人には本当に意味が分からないかと思います。。
そして、AIRを知ってる人も結局は意味が分からないかと思います。
(追記)
Google Mapなのが分かりにくかったので、
縮尺を変えて露骨に地図を表示するように変更。