PostScript でチャーチ数(が書けてない)
前フリ
Mixi の C/C++ の課題丸投げコミュで,ポストスクリプトで〜せよ.C言語です.
とか書いてあって,あまりレスされてなかったので,
PostScript の勉強を兼ねて書き込んでみた.
PostScript で,円弧(arc)や線分(lineto).塗り潰し(fill)をするのは簡単なので,
比較的スムーズに課題には答えることができたが,
PostScript の名前空間(辞書,dict) がよくわからなかったので,
ちょっと探して,わかったのことをまとめておくことにする.
というか,PostScript でチャーチ数を書きたかっただけです.すみません.
前提知識
- PostScript は,プログラミング言語である.
- PostScript は,逆ポーランド記法で記述し,スタック指向で処理される.
- PostScript の処理系は,GhostScript (gs, gsnd).
- PostScript のコメントは,% から行末まで.
- トークンには,データと実行可能なものがある.
- [ 1 2 3 ] で配列
- { 1 2 3 } で,処理をまとめる.
- シグネチャが,「引数 関数名 スタックに返す値 」のようになっている
- add 関数だと,「num1 num2 add sum 」で,add という関数名で2引数をポップして,スタックに sum を返す感じ.
逆ポーランド記法で〜の辺は,こんな感じ.
print(10 + 20 * 30) を表現しようとすると,こんな感じになる.
10 20 30 mul add ==
擬似的に実行してみると.
- 1. まず実行可能じゃない 3つを積む.stack => (top) 30 20 10 (bottom), com => (mul add ==)
- 2. mul が来たので,スタックトップから2つ消費して,計算結果をまた積む.stack => (top) 60 10 (bottom), com => (add ==)
- 3. add が来たので,同様に,stack => (top) -590 (bottom), com => (==)
- 4. == が来たので,スタックから1つ消費して,-590 を表示.stack => (top) (bottom), com => ()
gs は,インタラクティブモードで PostScript ファイルを表示しようとするけど,
gsnd は,NoDisplay の略らしく,
バッチなら gsnd -q -dBATCH
インタラクティブなら, gsnd -q を基本とする.
で,コピペ.(コメントは筆者)
/closure{ [ countdictstack array dictstack [ exch{ dup systemdict eq{ cleartomark mark systemdict }if }forall ] { begin }/forall cvx % ここまでで名前空間を実行可能オブジェクトに保持 counttomark 2 add -1 roll % スタックからクロージャの中身を挿入して保持 /stopped cvx 4 index length{ end }/repeat cvx { stop }/if cvx % エラー処理 ]cvx }def
closure は,参考のところからコピーしたので,
内容を読んでみる.
以下は,bluebook からコピペした,シグネチャ.
関数名は,()括弧で囲んである.
- - (countdictstack) int : count elements on dict stack
- int (array) array : create array of length int
- array (dictstack) subarray : copy dict stack into array
- array proc (forall) - : execute proc for each element of array
- bool proc (if) - : execute proc if bool is true
- mark obj_1..obj_n (cleartomark) - : discard elements down through mark
- any (dup) any any : duplicate top element
- a_{n-1}..a_0 n j (roll) a_{j-1 mod n}..a_0 a_{n-1}..a_{j mod n} : roll n elements up j times
- - (stop) - : terminate stopped context
- any (stopped) bool : establish context for catching stop
- any_n..any_0 n (index) any_n..any_0 any_n : duplicate arbitrary element
- array (length) int : number of elements in array
- int proc (repeat) - : execute proc int times
- any (cvx) any : make object be executable
補足
- stop / stopped は,throw / catch 関係のようなもの,stopped ブロック内で stop すれば,true を返す.
- cvx がeval みたいなもの.
で,書いてみたんだけど,two がうまくいかない.
ふーむ.何か勘違いしてるのかなぁ?
% zero(f)(x) => x /zero { 1 dict begin /f exch def /x exch def x end } closure def % n + 1 => f(n(f)(x)) /inc_cn { 1 dict begin /n exch def { 1 dict begin /f exch def /x exch def x /f cvx n f end } closure end } def % m + n => n(f)(m(f)(x)) /add_cn { 1 dict begin /n exch def /m exch def { 1 dict begin /f exch def /x exch def x /f cvx m /f cvx n end } closure end } def /one /zero cvx inc_cn def %/two /one cvx inc_cn def /two /one cvx /one cvx add_cn def (: print zero) == 0 { 1 add } zero == (: print one) == 0 { 1 add } one == (: print two) == %0 { 1 add } two ==
参考
- d:id:yshl:20091031:1256990002
- http://www.cs.kyoto-wu.ac.jp/~konami/documents/ps/PLRM.pdf - Postscript Language Reference Manual
- http://www.cs.kyoto-wu.ac.jp/~konami/documents/ps/ - リンク集