Archive for 8月, 2008

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は、スペシャル変数があるのに、
なんでスペシャル関数がないんだという、どうでもいいことに気づいてしまいました。
ほんと何でないんでしょう。使い道がないからなのか、スペシャル変数で代用できるからなのか…

禁断の乗り物CDR(クダー)の謎を追え!

日曜日, 8月 31st, 2008

データを入れるところが2つある箱をコンスセルという。
左側の入れ物がCAR(カー)で右側がCDR(クダー)。
どうして左側がCARなのか分かる?
車は左側通行だからさ!

Lisp初学者が一度は聞くことになる(と私は思い込んでいる)決まり文句です。
しかし、ここで誰もが疑問に思うのが「CDR」の存在です。
CARが左側通行の乗り物ということは、CDRという右側通行の乗り物があるのでしょうか。
しかし、CDRの正体を尋ねてみても、
「そんなCDRらないことを聞くな。」
と、お決まりの返事をされ、結局CDRの正体を教えてくれません。
ひょっとしたら皆が決して触れようとしない、「クダー」という名の乗り物が存在するのではないのか。
そして、真のLisperのみが隠れてクダーに乗っているのではないか。
そう考え、私なりに色々と想像してみました。
「クダー」という独特の響きや、皆が触れようとしないという事実から察するに、
従来の乗り物とはまったく異なるものではないのでしょうか。
そんなことを悶々と考え、出た結論がこれです。

▲ぼくの考えたクダー

▲クダーに乗車する図
あ、車とは異なるので「乗車」という表現は間違っているのかもしれません。
まあ、そんなことはこの際どうでもいいので放っておくことにします。
それから、乗り物であるからにはいろんなカラーリングがあるのでしょう。
きっと並べてみたらこんな感じです。

▲クダーいろいろ
これはあくまでも私の想像図ですが、きっと本物のクダーからそれほどは遠くないでしょう。
クダーに乗ったことがある、もしくは乗っている人を見かけた方は是非私までご連絡下さい。
あ、CDRはContents of Decremental part of Registerの略という説もありますが、
きっとこれはクダーの存在を隠すために意図的に流された噂でしょう。
いわゆる「政府の陰謀」というやつですよ。騙されてはいけません。

第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なのが分かりにくかったので、
縮尺を変えて露骨に地図を表示するように変更。

適当にLispネタ

火曜日, 8月 12th, 2008

キーボードの「8」のキーが壊れて以来、
ろくにLispのプログラムを書いてないので、適当にネタを拾って、
忘れないように書いておきます。
以下は、2chのLisp Scheme Part23より。

131 :lischemep ◆/uyHCgG7qA :2008/08/10(日) 23:28:50
都内で初心者向け勉強会を模索しようとしております。
以下想定です。
こうしたらいいとかありましたらどんどん提示して頂けたら幸いです。
・大学生のLisper/Schemerを先生として呼ぶ
・上記のため会費をとります。
・場所は以下を想定。(1h:1400~2300円くらい+各自1ドリンク)
ttp://www.ginza-renoir.co.jp/miyama/
・スキルがバラバラになるため基本的に自習を想定
(同スキルの人と課題本を決めてチーム学習する等は自由です)
・参加条件としてキーボードがサクサク打てる程度。処理系を入れるノートパソコン等。
・開発環境構築から指導の予定
参加者希望予定者がいらっしゃいましたら、
lischemep at gmail.com
まで下記を記入して送ってください。
使用希望の
・希望日(参加頻度:必ず参加、月1希望、仕事のため不定等)
・希望参加費
・OSとバージョン
・エディタ
・処理系
(↑処理系は希望なければおまかせと書いてください)
また先生やってみたいという方は、下記を記入して送ってください。
・希望日(開催頻度も)
・希望報酬額(時給換算、月XX円等)
・対応できるOS・処理系・エディタ


あと、学生を講師にするのに、金を払うという発想はなかった。
お金という直接的なものを渡すのはなんだか生々しい気が…
(終わった後に宴会開いて、講師は宴会費無料とかだったら個人的には嬉しいんですが(笑))

149 :デフォルトの名無しさん:2008/08/12(火) 00:57:31
>>145
国立大は社会人受入れに寛容
なようなので正規に聴講生の
手続きをとって試験も受けて
単位もとりたいです。
でも、地方の大学でSchemeを
使った講義があるところは
限られてるみたいです。


うちの大学はSchemeの講義なんてないよなーなんて思ってたら、
実はとある授業で部分的にやっていたようです。
試験問題にSchemeの問題が出てきて気づきました。
(なんで授業中に気付かなかったって? そりゃ授業に行ってな(ry…)

161 :デフォルトの名無しさん:2008/08/12(火) 02:47:46
>>159
最初の頃はFSUBR + EVALで一々手で書いた。
パターンが出来上がったのでdefmacroになった。
>>156
> 自習だとつまらないことでつまづいて長い時間考えることがあるからです。
本当はそれが大切なんだけどね。
より深く理解するし、それが出来る人が継続もできる。
壁に負ける人はいつも負け続ける。


最初の頃はFSUBR + EVALで一々手で書いた。」ですか。
私は自分でインタプリタを作るときはいまだにこれです orz

話は変わるんですが、「実践Common Lisp」の脚注に

*10 大雑把に言うとMODはPerlやPythonの%演算子と等価であり、REMはCやJavaの%と等価だ
(記述的に断っておくと、Cにおける%の振る舞いはC99まで規定されていない)。
P118 10.4 数値比較

なんてことが書いてあったんですよ。
Cでは負の数の剰余はどうなるか定められてないと思い込んでいたら、
実はC99でしっかりと決まっていたんですね。

夏休みはじまたー

金曜日, 8月 1st, 2008

いつの間にか試験が終わって夏休みになりました。
わーい。
そんな訳で、プログラミング欲がゲーム欲に負けて昨晩はエクスタシーな日になりましたよ。ええ。
とりあえず、朱鷺戸さんかわいいよ朱鷺戸さん(*´Д`)
といった感じでした。それにしてもよくゲームオーバーになりました。
多分、Key史上最も沢山ゲームオーバーになる(可能性が高い)シナリオです。
それから、終わったあとのもやもや感はAIRのオチを見たときに似てます。
あと、性能の悪いマウスやノートPCのタッチパッドなんて使ってたら、
ミニゲームが死ぬほど大変です。というか、死にます。冗談抜きに。

CLで作っているWikiですが、必要最低限の機能が完成したので、
こっそりと身内に公開して、苛めてもらってます。
いまのところ、突然落ちたりすることはないようです。
この夏の間に一般に公開しても大丈夫なものにしたいものです。
前のエントリーでCLの改行コードについて書いたら、
色々とお話を聞けたので、簡単にまとめておきます。
*行末のCRを消す*

;; deleteを使う
(delete #\Return line :from-end t :end (length line) :start (1- (length line)))
;; string-trimを使う
(string-trim '(#\Return) line)
;; string-trim-rightを使う
(string-trim-right '(#\Return) line)

他にもadjust-arrayを使う方法などがあるようです。
*文字#NewlineをCRLFとして扱う*

;;external-formatに指定 (CLISP only)
(make-encoding :charset "Shift_JIS" :line-terminator :dos)

ただ、ストリームの改行コードをCRLFとして開くと、
#\LinefeedもCRLFとして扱われてしまうみたいです。恐ろしや。
こうなると、LFだけを出力するのが面倒になるとか。