Lingr:まとめ
Gaucheの部屋のまとめです。WebベースのチャットサービスLingrを使っています。
- 2006-11-12 (Gauche 0.8.8リリース、Sumibi.orgの中の話)
- 2006-11-11 (Gauche 0.8.8リリース最終段階)
- 2006-11-10 (Gauche 0.1、one-liner)
- 2006-11-09 (Schemeのダメなところ、雑談)
- 2006-11-08 (quasiquotation)
- 2006-11-07 ("kaze"を抜く、不完全文字列、Kahua)
- 2006-11-05 (Meta Object Protocol)
- 2006-11-04 (OnLisp出版の状況、debug-print、Gauche 0.8.8)
- 2006-11-03 (シェル、Scheme式を評価するC API、健全なマクロ)
- 2006-11-02 (Binary Hacks、shiroさん)
- 2006-11-01 (デバッガと最適化、木の差分、gensym)
- 2006-10-31 (「#?=」の再定義、ヒストリ、weak hash table)
2006-11-12 (Gauche 0.8.8リリース、Sumibi.orgの中の話)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/11
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/12
普通のやつらの斜め上をいく
- 昔transmetaがSchemeプログラマ募集してたことがある。schemers.orgに出ていた。検証ツールがschemeで書かれてるとかなんとか
- ZendのPHPコンパイラもSchemeで書かれているというのをどこかで読んだような気がします
- DI (依存性注入)などは複雑。再利用性を求めるなら関数指向。言い替えれば、再利用しやすいのはアルゴリズムであって、モデルではない (モデルはむしろ個々の問題specific)ってことなのかもしれない。
Ajaxなかな漢字変換Sumibi.org
- mixiとかでsumibiはちょっともっさりしているという意見がある。MySQLのDBクエリが一番重い。select sum()/ entrys where a=1 or a=2 or a=3 .... みたいな巨大なクエリが発行されるので。要するに統計情報の集計を毎回一からやっているので。富豪的。セレブ的。
- a b c とあったら、 a b 、 b c 、 a c の共起回数を記録していっています。→なるほど。それでlookup時にsumを取ってるなら相当重いですね。今の速度で動いてるのがすごい。
- メモリは4GB。MySQLには3Gまでグローバルキャッシュを使うように設定しているのですが、indexなどのキャッシュなどが1時間程度の利用でいっぱいになります。あと、クエリキャッシュの威力が大きい。DBに書き込みが起きるのは今のところ数日に1回。前はリアルタイムに学習データをリプリケーションでつっこんでたんですが、クエリキャッシュが全てムダになって遅かった。
英語
- OSCONのpodcast (IT conversatins)とかは、聞きやすいやつが多い
- (kiyokaさん) 4年くらい毎日Podcast聞いているんですが、やっと細かいところが聞こえるようになってきた。ぼそぼそ言ってるのも聞こえるようになってきた。
- 海外にいても、日本人の多いところとかだと積極的に求めないと英語漬けにはならんです
Gauche 0.8.8リリース
- 半年以上も開いちゃったのか。良くないなあ(shiroさん)
- 拡張モジュール全部入れなおし。→ gauche-package list -a で出てくるやつを自動的に全部入れ直すコマンドとかあるといいかなあ。ソース置き場を統一しないとならないけど。
ポート入出力の速度
- enamiさんによるPORT_LOCK周りを変えるパッチ。OSによって早くなったり遅くなったり結果が違う。
2006-11-11 (Gauche 0.8.8リリース最終段階)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/10
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/11
rxmatch-caseの正規表現でインデントが崩れる
- (RE (VAR ...) FORM ...)の形でFORMを次の行にもっていったときに、FORMに対する字下げが、上の行に出てくる最初の括弧のところになってしまう
- 正規表現については、Gaucheのシンタックスを理解するようなメジャーモードを作るしかないでしょうなあ。私はその都度そこだけ手で直してますが、ついC-M-SPC C-M-\するとインデントが崩れて悲しい思いをします。
- 正規表現(というより#/で始まる場合)は、インデントを#の位置にそろえてしまうEmacs Lispコードが出た。
- 特殊な意味づけが無い文字については、バックスラッシュをつけても無視されるので、バックスラッシュをつけて逃げている。将来の拡張を考えるとマニュアルに記述の足された\;, \", \#だけにバックスラッシュをつけるのが安全。
Gauche 0.8.8リリース最終段階。practical-scheme.netのgaucheを入れ替えて検証中。この後、リリースノート書いて、rpm作って、サイトアップデートして… まあ明日中くらいには出せるかなあ。
HaskellのPersec的なものをSchemeで書いてみた。適当にリリースされる予定。
2006-11-10 (Gauche 0.1、one-liner)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/09
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/10
成功したLispハッカーPaul Grahamがやっているベンチャーファンドの記事 Y Combinatorカンパニーって誰?
"Scheme"は検索しづらい。"C"よりはまし。"Gauche"もやや辛い。その点高林さんは昔から名前の検索性をよくかんがえていた。Namazu、Migemo (ローマ字のまま日本語をインクリメンタル検索)。
STkの後継、STKlosは完全にスクラッチから書き直したもので、VMにコンパイルして実行する処理系。Eric Gallesioさんは大学の計算機センターかなんかの面倒もみてて、そこでのツールをSTklosで書いてる、って話をBiglooの中の人(Manuel Serranoさん)から2003年頃に聞いた。
- STKlosのリリースがもう半年早かったら、Gaucheは生まれてなかったかも。多分stklosが出てれば積極的にそっちにcontributeしてたと思う(Shiroさん)。
Gauche 0.1 (5年前)をチェックアウト
- cvs -d:pserver:gauche.cvs.sourceforge.net:/cvsroot/gauche co -D '2001-03-03' -d gauche-0.1 Gauche
- コンパイルにはSTKとShiroさん自作ライブラリstklibがいる
- 現在のgccでコンパイルするパッチが出たが、STKが必要ゆえにコンパイル挫折
Schemeプログラムの全文字中のカッコ比率はどれくらいだ?
- Perl手抜きワンライナ ~/proj/gauche$ find . -type f -name \*.scm|xargs perl -ne 's/;.*//; print join "\n", split //'|sort|uniq -c | sort -nr
- 135448 e, 116825 (, 116359 ), 104941 t, 83626 r, 83625 a, 83197。やはりカッコが多い
- Haskellワンライナ cat `find -name *.scm` | ghc -e "getContents >>= mapM_ print . reverse . Data.List.sort . map (\\xs -> (length xs, take 1 xs)) . Data.List.group . Data.List.sort"
- nobsunはいつもこんなワンライナを書いているらしい
- 無理矢理Gaucheでワンライナ cat `find . -name "*.scm"` | gosh -uutil.list -e '(for-each print (sort (hash-table->alist (port-fold (lambda (c tbl) (hash-table-put! tbl c (+ (hash-table-get tbl c 0) 1)) tbl) (make-hash-table) read-char)) (lambda (v1 v2) (< (cdr v2) (cdr v1)))))'
2006-11-09 (Schemeのダメなところ、雑談)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/08
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/09
Schemeのダメなところ
- かっこがたくさんあるところ(Schemerならいやとは思わないが、さすがにホワイトボードにアルゴリズムを書くときは括弧よりインデントを使う)
- ライブラリの少なさ(メジャーな言語も最初からたくさんあったわけではない)
- 実装がたくさんあってどれ使えばいいか悩む
- 再帰的な考え方を覚えないと使えない(それは覚えてくださいと言うしか)
- 再帰わからなかったら大事なアルゴリズムの大半は理解できないでしょうに。それ抜きで書けるプログラムはかなり限られるような。アルゴリズムが再帰なら、それを再帰無しで書いても実質的には自前でスタックを管理してることになるから、そのオーバヘッドと関数呼出しのオーバヘッドのどっちが重いかってことだよね。
- 関数は重いと誤解されている
foldのあの動作がなぜ「畳み込み」なのか?
- ええ、なんか駄菓子屋で売ってるベビースターラーメンの小さい袋のつながったやつをぱたぱたぱたっと畳んでゆくような感じがしない?
gauche-configのオプションのシェル補完を作ってみた(bash、zsh)
時間の計算は面倒
- sys-strftime、自作のhhmmss->sec、コード片など
2006-11-08 (quasiquotation)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/07
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/08
ネストしたquasiquote、unquote
- `(,a ,b) => (1 2)
- ``(,a ,b) => `(a b) ;; これが `(1 2) になると思ってた
- ``(,,a ,b) => `(,1 ,b) ;; これも `(,1 2) になると思ってた
- x => (1 2 3), y => (9 8 7)
- ``(,@x ,@y) => `(,@x ,@y) ;; これも先に展開されると思ってた
- ネストしたquasiquoteを扱ってる論文: Quasiquotation in Lisp。歴史のトリビア。MITのLisp machineプロジェクトでは,@Xを,,Xと書いていたので、ネストしたquasiquoteのunquoteと干渉していたんだけど、その当時はネストしたquasiquotationが「きちんと動く」と思われていなかったので問題にならなかったそうな
Shiroさんは子供が出来てから、夜に十分睡眠がとれない。子育てに一番必要なのは、経済力でも親としての人格でもなくて、体力だと思います。ひたすら。
Kahuaのsandboxはいらないのではという議論。1.0までは現状のまま。1.0のあとに考えてみる。
2006-11-07 ("kaze"を抜く、不完全文字列、Kahua)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/06
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/07
TzWatch: Lingr用の時刻表示アプリ(Gauche + Gauche-gdで作成されたCGI)。ソースコードを整理したらBSDライセンスでリリースされそう。http://www.sumibi.org/lingr/tzwatch.cgi
「風邪が抜けねぇ」発言から始まったネタ(A-Zからkazeを抜く)
- bcdfghijlmnopqrstuvwxy
- Haskell: ['a'..'z']>>= starling ((>>) . guard . flip notElem "kaze") return
- Scheme (SRFI-42): (remove-to <string> (pa$ string-index "kaze") (string-ec (: c #\a #\z) c))
- 改良版: (string-ec (: c #\a #\z) (if (not (string-index "kaze" c))) c)
- さらなる改良版: (string-ec (: c #\a #\z) (not (string-index "kaze" c)) c)
- (char-set->string (apply char-set-delete #[a-z] (char-set->list #[kaze]))) => "yxwvutsrqponmljihgfdcb"。逆順だけど、char-setは順不同だから順番あてにしちゃだめ
不完全文字列
- いずれは正規表現が不完全文字列も許せるようにしようかと思ってる。
- 文字列にまぎれこんだ怪しいバイトだけを特別扱いできるような感じにしたい。一度不正バイトが入った文字列を掴むと、そこから何かするのが難しいんだよね、今は。
- string-incomplete->completeで、不正バイトを除いちゃうようなオプションつけようか。get-output-string->u8vectorみたいのを作っちゃったほうがいいかな。
- 文字列ポートにwrite-byteしてって、最後にget-output-stringすると、基本的に完全文字列にしようとする。常に不完全文字列がほしければstring-complete->incompleteするとよい。アロケーションを避けられる(フラグだけ変える)string-complete->incomplete!という手続きがあるが、これはMT (multi-thread)-unsafeなのでdeprecated。使わないでね。
感動したプログラム言語 Piet - http://www.dangermouse.net/esoteric/piet.html [image]
Kahua 1.0
- 年内に1.0出すぞ、という話。
2006-11-05 (Meta Object Protocol)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/04
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/05
Scm_Require、Scm_LoadのAPIを変える(引数を増やす)と困る人はいるか? 拡張モジュールでは使わず、Gauche組み込みで使われるAPI。
非公開だったR6RS editorsのメーリングリストのアーカイブが公開されている(アナウンス)。r6rs.org、r7rs.orgは取得済みだが、r8rs.org以降は空き。
Gauche関連のブログをチェック。GaucheとGTKを使ったエディタ作成中、ネイティブコードを生成しようという構想がある様子、Schemeのサブセットを書き始めている、Scheme演習に挑戦中。
karetta.jpで「記事の時限公開」をするために、MOPでスロットアクセスを制御
- あらかじめ与えておいた時刻と現在時刻を比べて、その時刻より後のときにアクセス可能なスロットというのをMOP (Meta Object Protocol)で作る。setterではなくgetterをカスタマイズしたいのでGaucheRefj:gauche.mop.validatorは使えない。
- :enable-timerというスロット定義オプションを認識する<timer-meta>メタクラスを作り、getterをカスタマイズ。カスタムのgetterはインスタンスのdisplay-dateスロットの時刻を現在時刻と比較して、まだアクセスを許さないなら#fを返す。<timer-meta>をメタクラスとするクラス<timer-mixin>を作って、それをスロット定義をカスタマイズしたいクラスの親クラスとする。
- <timer-mixin>はdisplay-dateとprivateスロットを持つことが前提になってるので、クラス定義を間違えるとスロットが見つからないエラーになる。しかしmixinにスロットを持たせるとスロット定義が分散して見にくい。こういうのは契約(contract)なので、文書化しておくとか、必要なスロットへのアクセスをジェネリックファンクションにしといて mixinでデフォルトメソッドを提供、子クラスでオーバロードしてもらうとか、あとはmixinのメタクラスのcompute-slotsで欲しいスロットがちゃんとあるかチェックするとか。
- ベースクラスやmixinは多重継承しないほうがよい。多重継承は強力だけど、トラブルが起きると解決が面倒。mixinはJavaのinterface的に使って、クラスは原則として単一継承で、末端の部分でmixinを入れて行くのがよい。
- しかしkaretta.jpでは記事が公開された瞬間にrss.xmlファイルを書き換えなければorzなのだった。MOPによる解決策はなし?
2006-11-04 (OnLisp出版の状況、debug-print、Gauche 0.8.8)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/03
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/04
GaucheFest第17回 (GaucheFest:17th)の日
Gaucheの部屋は、Anonymous observerを足すと10人を超える参加者で、Lingrの中で一番トラフィックが多い。
野田(flatline)さんのOnLisp翻訳。オンラインで読める。flatlineさん: 出版を遅らせてるのは純粋に私。出版は現在査読者からの意見を取り込んでいるフェイズ。本業の方に時間を取られて、なかなか。
CVSからチェックアウトした状態から、Gaucheのビルドにかかる時間は? Pentium M 2.26GHz (NetBSD 4.99.3)で3分半、Core Duo T2400 1.83GHz (Ubuntu 6.06 on VMware)で3分弱、Core Duo 2.0GHz (MacBook)で2分弱。
debug-print (#?=)のカスタマイズ
- cut-seaさんがいろいろ試行。trace風表示でインデントさせたりとか。
- shiroさん: #?=file:line形式は実はemacsからソースにジャンプしたりとか考えていた。他に #?! で debug-breakというのを考えてて、そこで#?!file:lineとか表示してデバッガに入るとか。そうするとgdbみたいなインタフェース書けるなとか。カスタマイズはいずれ入れます。0.8.8に間に合うかどうかわかりませんが。
Gauche 0.8.8リリーススケジュールはわからん
- shiroさん: 残りは、Ruiさんの未使用モジュールの検出、びさんのGCのパッチ(Mac OS用)の取り込み。WiLiKiに報告されてるバグをつぶして、複数プラットフォームでの検証。コンパイラのwarningは-Wallにしてつぶしている。
ruiさん: 文字列へのシーケンシャルなアクセスする方法がstring-pointer以外なくて困る。string-pointerは推奨されていない。srfi-13はシーケンシャルアクセスするようなAPIを提供してない。portだと1文字以上ungetできないので汎用ではない。だから2文字以上先読みが必要なパーザ書くときstring-pointer使いたい。
- shiroさん: 無限先読み可能なポート、というのを(virtual portで)作るか、srfi-68のstreamみたいに入力するたびに「データ+次の状態」を返すfunctionalなインタフェースを作って、バックトラックしたい時はその時点の入力を掴んでおくか。
- ruiさん: 未処理のデータというのを文字列そのもので持つか。
shiroさん: mmapはいちおう考えてる。ただ、unmapされた時にそこを指しているポインタをどうするか考えないとならない。uniform vectorにownerというポインタがあるのはそのへんの伏線のつもり。
GaucheFestやり方を見直した方がいいかも。年内2回やったら再検討しましょうか。徐々に集まり悪くなってきてるし。明確にネタを持ち寄ってあーだこーだじゃなければ、集まる必要もない。
2006-11-03 (シェル、Scheme式を評価するC API、健全なマクロ)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/02
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/03
シェルの話
- scsh (Scheme Shell)を使うんだけど続かない。cshスクリプト禁止。shと思い込んでbash拡張ばりばり使ってしまう。zshの**/*は便利(grep keyword **/*.cでディレクトリの下の*.c全てをgrep)。そういうときにはfindを使うが、空白が含まれているときはfind . -print0 | xargs -0などとしてヌル文字区切りにする。Mac OSでは空白を含むディレクトリがあるのでハマる。bashのglobは!(*~)で「~で終わらないファイル」というようなことができる。
SRFI-61とSRFI-87をサポートするパッチがメーリングリストに流れた。
CからScheme式を評価するAPIの検討話
- 0.8.7までのScm_Eval, Scm_Applyは、CからScheme式を評価するのに使えるAPIだったのだけど、エラーを捕まえてくれないので、ちゃんと使おうと思うと実は使いにくい。
そこで、エラーをちゃんと捕まえてくれるAPIを別に用意して、いずれはそっちをScm_Eval, Scm_Applyなどと呼ぶように変更する予定。移行期間は設けるけど、この新APIは、結果をCの構造体に返す。で、「Scm_Eval(ScmObj expr, ScmObj env, ScmEvalPacket *packet)」みたいに呼べば、多値が返ってきてもOKだし、エラーが発生した場合はそれを捕まえてpacket->exceptionフィールドに入れてくれる。
で、この関数の戻り値の型をどうしようか悩んでいる。(1) intにして、正常終了なら値の数、エラーなら-1を返す (2) ScmObjにして、正常終了で値が1個以上あればその値、それ以外の場合はたとえばSCM_UNDEFINEDとか返す。
前者は、わりとエラーチェックをencourageする形式。結果を取り出すのにpacketにアクセスしなくちゃならないんで面倒。後者は、カジュアルな使用(多分エラーは起きないし、返ってくる値も1つだとわかっている)の場合にとても便利。だけど便利すぎてエラーを考慮しないコードがたくさん書かれてしまうおそれもある。The Right Thingなのは(1)だと思うんだけど、なんか(2)の手軽さも捨てがたいんだよね〜。ど〜しよ〜かな〜。
「エラーなんて起きないでしょ」なんて場合は ScmObj result = Scm_Eval(expr, env, &packet); みたいに書いてresultを使う方が簡潔ではある。 int status = Scm_Eval(expr, env, &packet); if (status > 0) { packet.result[0] ... } よりは。
evalに渡す環境は、Gaucheでは単なるモジュール
- env = module + α なんですが、現在はαの部分がないので、env = module。Schemeでのevalの第二引数に渡されるものも、(R5RSでは処理系依存の何かですが)Gaucheでは単なるモジュール。αの部分とは、ローカルな環境をキャプチャすることを許す場合とか。あるものだけを見せればいいなら何とかなるかも。まだフレームの構成とか変える予定だから、それが落ち着くまではデバッガの方には手をつけられない。
健全なマクロの話はどろどろ
- 健全なマクロが不健全なのは、「やりたいこと」はとっても健全なんだけれど、実装しようとすると落とし穴が多すぎるというかほとんど地雷源。で、そんなに複雑になるのは、実は問題の立てかたが間違ってるんじゃないかって感がぬぐえない。
- GaucheがPortable syntax-caseを取り入れていないのは、Gauche内部の識別子構造をうまく使えば効率良く実装できるんじゃないかと妄想してるから。
2006-11-02 (Binary Hacks、shiroさん)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/01
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/02
Gaucheでファイルをオープンするとき、open(2)のO_EXLOCKを渡す方法はあるか? O_EXLOCKを渡すとファイルオープンとロック取得をアトミックに行う。
- BSDと違ってLinuxにはO_EXLOCK自体ない
- ロックファイルを別に持つのが正統
APLで使う文字をLingrにコピペできる。トーフや「?」になる見える人もいる。フォントの問題か。
Binary Hacks、shiroさんが書いた序文をサンプルPDFで読める。
- 「抽象化のほつれ」の話はBinary 2.0 conferenceの話を聞いたときにwilikiに書いたのだけれど、それを見て高林さんが声をかけてくれたのがあの序文になりました。Joelが同じようなことを書いているってのもそのwilikiの書き込みから誰かに聞いたんだった。(Joelの、というのは、「漏れのある抽象化の法則」The Law of Leaky Abstractionsのこと。)
そもそもデジタル回路からして、アナログ世界を0と1にぶった切ってるけれど、実際に動いてるところはアナログそのものだからなあ。回路は絶対に合っているのに、クロックを上げたら動かないとか。手をかざすと動くとか。思うように動かせないのがすげー悔しかったなあ。
Q: いっかいshiroさんに伺いたいとおもってたんですが、プログラミングとくにコンパイラはとても詳しいですよね。実装経験も豊富そうだし。それってどこで学んだものなんですか?
- A: とても詳しいわけじゃありません。んー、どこで学んだんだろう。興味のあるのをつまみ食いしてたら、後から体系的な話を知って納得したって感じです。パージングとかは、中学生のころだったか、「数学と同じように計算できる電卓ってどうつくればいいんだろう」とかやたら悩んでて、なんとなくできそうな感じのやりかたを思いついて、大学でオートマトンを習ったらそれができそこないの演算子順位文法だったとわかったとか。AST作ってからコードジェネレーションまでは、修士の時にgccのソースを読んだのが効いていると思います。2.7.2くらいの時だったかな。あとSchemeのコンパイルについてはScheme->Cがすごく参考になった。あ、それからCP/M-80上で走るBSD Cっていう小さいCの処理系があってそれの吐くアセンブラコードも参考になった。(注:BDS Cじゃないかな?)
なんかコードジェネレーション以降の話は、そういう雑多な知識しか持ってなくてフォーマルな最適化手法をちゃんと勉強したことがないからいまいち。あと、型推論あたりもちゃんと勉強してないから怪しい。やっぱ自分で手を動かして実装してみないとならないと思う。芝居に明け暮れる、不真面目学生だったんです。
あ、あと、「耳年増」じゃないけど回りで高度な会話がなされてるのを聞いててわかんないのが悔しくてあとでこっそり調べたりしてると、だんだん知識がつきますね。そういう意味では、学会とか国際会議とかもっと学部のうちから積極的に行っとけばよかったって思います。大学院に入ってからだな、そういうのを意識するようになったのは。
あーそだ、関係ないけど、ドキュメント。学部4年の時から、小さなunix系のシステム会社でバイトしてたんですが、確かDECからスピンアウトしたエンジニアが作った会社で、私が入った時に5人くらいしかいなかった。そこでX Window system関係の仕事をけっこうやらされて、最初に、社員の人に「本屋に行ってXと名の付く本を全て買ってきて」って頼まれて、行ってみてみたら、日本語の本は薄いのしかないんだけど、英語のはあのO'Reillyから出てる巨大なマニュアルがあった。あれを読んで、あっちのプログラマはなんでこんなにドキュメントを書けるんだってびっくりしたんだけど、やっぱりこういうのを書けるようにならんといかんのかなと思って、それから意識してドキュメントはちゃんと書くようにした。他に影響受けたのはKernighan/PikeのThe unix programming environmentとかgccのinfo。
The unix programming enviornment は、上述の会社に行きはじめた時最初の仕事まで2週間くらい時間があって、勝手に勉強しといてって放っとかれてたんです。その時わたしはunixってほとんどわからなくて、ls, cd, cat, あとftpくらいだったかな、知ってたコマンドは。The unix 〜 は薄かったし英語がわかりそうだったので、それ読みながら空いてるマシンに打ち込んで、2週間したら電卓プログラムが動いてて感動した。
Q: Scheme処理系作る時に、最初readerを作る必要あると思うんですが、データ型はどの辺まで最初に作り込むんでしょう?
- A: 目的による。とりあえず作ってみたいのなら、pairと文字列さえ実装すれば、S式もどきのread/writeはできますよね。設定ファイルとかの目的ならそれでも十分。ここで言う「文字列」はもっとプリミティブな、シンボルと文字列兼用みたいなもの。
ただ、目的が実用的な処理系を作ることなら、後からの拡張を見越してデータレイアウトを決めとくのは重要だと思う。それとGCね。可変長オブジェクトを許すかどうかってのがまずひとつの決断。SCM方式(SCMの方式)では、全てのオブジェクトは固定長ヘッダを持ってて、可変長部分はいちいちmallocしたブロックをヘッダにぶらさげる。GCは固定長ヘッダのアレイをスキャンする。これを、可変長オブジェクトを許すことにすると、malloc/freeも全部GCが面倒を見るか。copying GCは綺麗なんだけど、ポインタが書き換わるから色々気を使わないとならない。可変長部分をGCに任せないとなると、可変長部分はリファレンスカウントにするか、共有を許さないか。SCMなんかは可変長部分はほとんど共有してないと思う。
2006-11-01 (デバッガと最適化、木の差分、gensym)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/10/31
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/11/01
- いまやGaucheの部屋はLingrのホットルーム
- 0.8.4からは、コンパイル時にクロージャ最適化がかかるので、プログラム上で見えているローカル変数がその通りに存在するとは限らない。以前あったインタラクティブデバッガは動かなくなった。0.8.8以降では、多分関数内にネストしたフレームを作らない最適化を試そうと思ってて、それをやるとますますプログラムの字面と実行時のイメージが離れる。やりたいことがステップ実行なのなら、portable scheme debuggerがやってるみたいにソースをプリプロセスして、全ての式の前にデバッガに制御を渡す呼出しを仕込んでしまうって手はある。これはread-eval-print-loopを細工してreadで読んだ式をevalに渡す前にいじるようにすれば可能。ただ、式がsyntaxか関数呼出しかで多分扱いを変える必要があるので、正しく実装するのはかなり面倒な気がする。より確実なやりかたは、コンパイル時にデバッグ用スタブを埋め込むようにすることかもしれない。
- debug-printの書き換えについては、今debug-print-widthをパラメータにしてカスタマイズしているみたいに、カスタマイズ用のフックを仕込んでゆくのがいいと思います。
- 値を書き換えるのは単純じゃない。というのはコンパイラは、スコープ内で書き換えが無い変数とある変数を全く別物として扱っていて、書き換えが無い変数はかなりリベラルな最適化を行っている (書き換えの無い変数っていうのはもはや変数じゃなくて、値についたラベルでしかない)。なので、そういう変数はもはやコンパイルされたコードでは「変数」としての実体をもたないので、デバッガから書き換えるのは至難の技。裏技としては、debug-printマクロ中で後からいじりたい変数を擬似的に書き換えるコードを挿入しておくって方法があり得る。それだとコンパイラは変数としての実体を保ったままのコードを生成する。
- ステップ実行は必要?
- ステップ実行ほしいよ派
- gdbでもステップ実行しまくりますよ派
- ステップ実行ほしいと思わないよ派
- ユニットテストでテストするよ派
- gdbでもbtとかくらいしか使わないよ派
- ステップ実行ほしいよ派
- 手続きの文字列表現が#<closure #f>のようになってるけど、以前は#<closure 0xXXXXXXXX>とアドレスが表示されていた。前のほうがよかった。 → アドレスを表示する数行のパッチ
- 木の差分を求めるアルゴリズム http://www.aichi-pu.ac.jp/ist/lab/yamamoto/pman2/data/pdf/41.pdf
- この論文で使っているアルゴリズムの原論文: http://www.cs.umaine.edu/~chaw/pubs/tdiff-sigmod96.ps
- gensymで作った(internされていない)シンボルかどうか判別する方法はあるか?
- シンボルテーブルに直接アクセスする方法はないが、(eq? sym (string->symbol (symbol->string sym)) が真ならinternされていると判別可能。ただしシンボルテーブルが大きくなってしまう。
- そもそもそういうことをしたい理由は? → 結局シンボルじゃなくてよかった(?)
2006-10-31 (「#?=」の再定義、ヒストリ、weak hash table)
http://www.lingr.com/room/gbq0WCLQEF2/archives/2006/10/31
- cut-seaさんのEmacsからgoshを実行すると日本語が化けるのは、Emacsのコーディングシステムの設定の問題だった
- R5.91RSはおもしろい
- Gauche本の話は存在していて、karetta.jpでそれなりに原稿が書かれていたりするけど、話が止まっている。shiroさんなら「これをお勧めしておけばOK」みたいなのが書けるんじゃないの。SICPは入門じゃないし。Practical Common Lispはよい。
- び(2006/10/31 14:40:33 PST): 「話が止まっている」というより、「なかなか思うように作業が進んでいない」が正確なところかも。
- Gaucheのコードは読みやすい。自分のわかってるところからよむといい。readとか。readは難しいからgauche.netみたいな独立したもののほうがいい。
- weak hash tableが欲しい。CのAPIが迷いどころ。
- Shiro(2006/10/31 16:18:56 PST): やりかけです。"Raw" hash tableを導入したのがその第一歩で、ScmObj以外のものをkeyやvalueに置けるようにしました。次のステップでkey, value, もしくはその両方でweak boxを使うような実装を入れる予定です。
- #?= をsyslogに出るようにしたい。→ debug-printマクロを再定義する、current-error-portを別のprocedural portにする、socklogを使う。debug-printはマクロだが再定義で変更できた。
- (make <foo>)とかしたあと、「ああっ、このオブジェクト使いたい」って思うことありませんか? → ヒストリが欲しい
- Shiro(2006/10/31 16:08:48 PST): http://sourceforge.net/mailarchive/message.php?msg_id=5609615
- edebugみたいなステップ実行が欲しい