Let's start Scheme

2011-06-30

思案中のこと

Sagittariusが遅い。
結構まともなライブラリを作ろうとしているのだが、それのテストというか1回走らせるのに2~3秒、長いときで5秒以上待たされる。ライブラリを除いた実際のコードは数行なのにだ。
これは、まぁ、原因まで全部分かっていて、コアの機能以外は全部そのときに読み込んで、コンパイル、実行しているからだ。さらに、マクロ展開の関係もあって、コンパイラがかなり重い。

っで、FASLを導入してみようかと思ったのだが、これって単にS式をバイナリにしただけなのね。それでは結局上記のルーチンが走るので美味しくない。どうやら本当に必要なのはCompiled Cacheのようだ。

名前などどうでもよくて、それが要ると思って考えていたのだが、いろいろ解決しなければならない問題が既にある。

・ライブラリ単位にするか、ファイル単位にするか。

どちらも問題があるが、ライブラリ単位がすっきりしてると思うのでそっちで。

・複数ライブラリが1ファイルにある場合はどうするか?
・ライブラリ外でモジュールを読み込んでからライブラリを作成しているファイル(実際既にある)ものはどうするか?
・どの段階でキャッシュするか?
・実行ファイル内(この場合は起動ファイルを指す)で、ライブラリを定義した場合にそれをキャッシュするか?

思いついたというか、考えている段階で答えが浮かばなかったのがこの辺。
4つ目は最悪キャッシュしてしまえばいいか。っで、import時に引っ掛けると。ただ、キャッシュ時間が問題になりそうだ。

さて、どうしようかな。

日本人がオランダに長くいすぎてしまったと感じるとき

これの逆版
あんまり思いつくこともないんだけど、面白そうだから。

1.電車やバスが10分以上遅れてもなんとも思わない。
日常的に10分くらい遅れる。というか時刻表はたんなる目安でしかない。

2.自転車が歩道を走ってると警察を呼びたくなる。
自転車用の道があるんです。

3.シリコン製のへらを日常的につかう。
けちなオランダ人は、洗う必要がなくらいきれいにビンの中身を食べます。

4.大麻のにおいが嗅ぎ分けれるようになった。
一応、コーヒーショップの外では吸ってはいけないはずなんだけど。

5.休暇が1週間だと短いと感じるようになった。
まとめて取れるんです。

6.残業する人を見ると可哀想だなぁと思うようになった。
まぁ、滅多に見ないけど。

7.自分は背が低い方だと思うようになった。
成人男性の平均身長185cmだったかな?

ネタが尽きた。
7個とは微妙すぎる数字だ。
なんかあったらまた書こう。

単に行き詰っていたので息抜きに書いてみたとも言う。

2011-06-28

発見し難いバグ

原因を特定しにくいと言うべきか。
まぁそんなバグに悩まされている。Javaや元々GCがあるような言語なら問題ないのだが、(ここまで言ったら何の問題かすぐ分かるが)、メモリー管理の問題である。

現状SagittariusではBoehmGCを使っている(そのうち取り替えてやる!と思っているが、GCはむずい。。。)。別にGCが悪いというわけではなく、どこかでメモリー破壊が行われている可能性があるとう問題。
読み込んだシンボルが、ある特定のプロセスを踏むと変更されている。発現性は100%なのだが、場所の特定ができない。この前、正規表現を実装している時に同じ現象が起きた。そのときは割り当てたメモリを越えて値を埋めていたので起きたのだが、その際の原因は非常に簡単で、メモリのサイズの計算が行われていなかったというもの。
例えば、mallocでintの配列10個確保するのにこう書いてたという問題:(int)malloc(10)
JavaやC++やってるとnew演算子が便利すぎて忘れる問題の一つだと信じている。信じたいとも言う。っが、今回はどうも違うらしい。メモリ割り当ての箇所を全部チェックしたが問題ない。ということは、割り当て時の不具合ではなく、使用時の不具合なので、それが使用されている箇所を全部洗いなおす必要がある。正直、砂漠の砂を数える気分になる(そんなにはないが)

どこかにいいメモリ破壊検出ツールはないだろうか?

2011-06-26

(match)ライブラリで見つかった気になるバグ

Sagittarius Schemeは一応Andrew Wrightのパターンマッチが使えるのだが、それを使用したプログラムで起きた気になるバグの話。

現在Sagittarius SchemeではCとSchemeを繋ぐ仕組みとして.stubファイルを使用している。ちなみに、アイデアはGaucheからいただきました。っで、そのファイルをcgenというSchemeで書かれたプログラムに処理させてCのファイルを生成する。利点はわずらわしい引数の数のチェックとか、型チェックとかをそれなりに省略できることと、Schemeのマクロチックにマクロを記述でき、かつそれらが確実にインライン展開されること。実際、.stubファイルから生成された.cファイルはサイズが4倍程度に膨らむ。つまり記述量が4分の1ですむということ。
話がそれた。そのプログラムでは上記のmatchを使っているのだが、最近変更したsyntax-rulesをsyntax-caseで実装するというので問題が起きた。matchの中で'_が単なるシンボルとして比較されていたのだが、syntax-rulesで生成された後のS式は全部ラップされて識別子になっている。っで、'_の比較が失敗するというもの。
何が気になるかというと、これからもしmatch相当の何かを書くことがあった場合、この辺を気にしないといけないということと、他のR6RSの実装ならその辺を気にしなくてもいいということ。正直、他の処理系との移植性は大分あきらめた部分はあるのでどうでもいいのだが、'_とか'...が識別子にラップされてもいいのかなぁとちょっと不安になってたりする。
現状動いているものを変更するのは怖いので(単に面倒くさがり)、とりあえず現状のまま様子をみて、問題が発生したら変えるということにしよう。

P.S.
Twitterをはじめました。アカウント名は@tk_ripleです。こういうところでさらしていいものなのかもわからないのですが、どうせ見てる人も少ないということで。

P.S.2
最初に登録したユーザー名から上記に変更してます。こんなものも変更できるのね、Twitter。

2011-06-25

めがね

前の眼鏡を5年以上使っていたので、新しいのを買った。
Tommy Hilfigerというブランド物である。まさか自分がブランドの着いたものを買うとは夢にも思わなかった。

つけた自分を鏡で見たときに、なんともトレンドな感じがして違和感を覚えたが、まぁいいか。

以下は余談。
こっちでは視力の指標に+-数字というのを使う。
例えば僕の視力は-6(左)と-8(右)という結果だった(ちなみに、マイナスは近視でプラスは遠視)。今まで日本の0.1とかと違って自分がどれくらい目が悪いのか分かり難い。
慣れの問題ではあるのだが、単位が変わるというのはいつでもそれに対応するのに困る。

2011-06-18

ぐぬぬ

syntax-rulesが遅いのでsyntax-caseで実装したものを試してみたら、動かない。いや、動くんだけど、正しく動かない。
その理由も分かったのだが、解決できる気がしない・・・

理由は分かれば単純なのだが、例えばこんなの。
;; testはR6RSテストスイートのマクロ
(test (let ((x 'outer))
   (let-syntax ((m (syntax-rules () ((m) x))))
     (let ((x 'inner))
       (m))))
 'outer)
これは割りと典型的な例で、マクロの中でマクロを生成すると起きる。(実は違うかもしれない)
この例だと(m)が返す値はouterじゃないとまずいのだけど、innerの方を返す。何故か?
syntax-caseがパターンとテンプレートをコンパイルする際にすべてのシンボルを識別子へと変換する。その際に、すべてのxが同一の識別子に変換されるので、let-syntax内にあるxとinnerそ束縛しているxが同一のものになってしまう。
これを回避するうまい方法が思いつかない。マクロの展開フェーズとコンパイルのフェーズが分かれていれば、マクロを展開する際に使用する環境やらマクロ展開フェーズやらがいろいろ知っていればいいのだが、現状の実装ではletが変数を束縛するということを知っているのはletに束縛された構文オブジェクトだけなんだよね。
また、マクロを展開してからコンパイルするわけではないので、マクロ展開中に変数束縛を作るマクロが出現した際に結局おかしくなる。
こうなってくると僕の足りない脳みそでが悲鳴を上げてくる。
現在の実装はYpsilonのものをSagittariusでも動くように適当にいじったものだが、根本的な理解をしていなかったため結構穴がある(例えば上記のものとか)。
この穴をふさぐためには実装のしなおしだろうか?しかし、そもそも今のモデルで上記のような問題を解決できるのだろうか?

・・・

考えるか・・・

2011-06-16

Socketが動いた!!

Socketの実装が完了。まだテストケース書いてないけど・・・

とりあえず簡単なechoサーバーを書いてみた。
(import (sagittarius socket))

;; creates echo server socket with port number 5000
(define echo-server-socket (make-server-socket "5000"))

;; addr is client socket
(let loop ((addr (socket-accept echo-server-socket)))
  (call-with-socket
   addr
   (lambda (sock)
     ;; socket-port creates binary input/output port
     ;; make it transcoded port for convenience.
     (let ((p (transcoded-port (socket-port sock)
          ;; on Sagittarius Scheme native-transcoder
          ;; uses utf8 codec for ASCII compatibility.
          ;; For socket programming it might be better
          ;; to specify eol-style with crlf.
          ;; But this sample just shows how it goes.
          (native-transcoder))))
       (call-with-port
 p
 (lambda (p)
   (put-string p "please type something\n\r")
   (put-string p "> ")
   ;; gets line from client.
   (let lp2 ((r (get-line p)))
     (unless (eof-object? r)
       (print "received: " r)
       ;; just returns message from client.
       ;; NB: If client type nothing, it'll throw assertion-violation.
       (put-string p r)
       (put-string p "\r\n> ")
       ;; waits for next input.
       (lp2 (get-line p)))))))))
  ;; echo server waits next connection.
  (loop (socket-accept echo-server-socket)))
これを起動しておいて、別ターミナルからtelnet localhost 5000で繋ぐと動く動く!!
あんまりにうれしいので、example/socket/echo.scmとか作ってしまった。初example!!

次はFFIでその次がGUIか。
GUIまでできたら実用的なアプリを書きたいなぁ。

2011-06-14

宗教観

<<警告>>
以下の文章は繊細な問題をダイナミックに否定しています。中東辺り発祥の宗教に属している方は読まないことをお勧めします。もし気分を害したり、聖戦だぁ!なんて言い出されても当方は一切責任を取りません。

身近な人がユダヤ教に改宗しようとしているのの関係で、元々宗教、特に中東辺りを発祥とするものが嫌いだったのに拍車がかかった。
とりあえず、前々から思っていたこととして、唯一神教は総じて腐っているということ。
何故か?こいつらの過激派は自分たちの神のためといって戦争を起こす。また、他宗教の人間を邪教徒といい虐殺する権利を持っていると言い放つ。実際、現在問題になっているテロリストの多くはイスラム教だし、歴史を紐解けばキリスト教が起こした略奪戦争は多々ある。
また、神父、宣教師、その他いろいろは神の言葉と称して人の洗脳を行う。その昔日本でも宣教師が神の教えと称し、奴隷として人々の売り買いをしたことは割と有名だと思う。そのため秀吉はキリスト教を全面的に禁止したとかしないとか(多分理由の一つだろう)

正直中身の教えに関してはどうでもいいのだが、とりあえずユダヤ教についていろいろ知ってしまった。まぁ、そのために嫌いになったという話もあるのだが。
とりあえず、ユダヤ教の好きになれない食べ物の話。
彼らにはKosher(日本語訳は知らない)というルールがあって、割と厳しく食べていいものとだめなもの、混ぜて食べてはいけないものがある。中でも一番気に入らないのは、Kosherな肉というやつだ。
正直何が普通の肉と違うのかはさっぱり分からないが、彼らの話によると、宗教上他の生き物の苦しみを体内に取り込んではいけないため、できる限り苦しまないよう殺した肉のみを食べるという。この段階で傲慢さがにじみ出てるなぁと個人的には思うのだが、まだまだある。豚は不浄な生き物なので食べない。魚はいいけど、海老とかは海の昆虫なので食べない。Unkosherなものを作った鍋は使ってはだめ、だってその鍋には苦しみが染み付いてるじゃん。
ちなみに、彼らによるとKosherでない肉はBAD MEAT(訳は適当に自分でどうぞ)なんだそうだ。つまり、我々が食べている肉は中に苦しみが詰まっていて、食べるには不浄な物なんだと。(そこまでは言ってないかも--;)
個人的にKosherとか単なる言い訳にしか聞こえなくて、「肉食べたいけど、教えに背くなぁ・・・よしそれっぽい規定作って食べれるようにしよう」という風にしか見えない。素直に菜食主義になれと言ってやりたい。(というかもう言ったが)

つらつら書き出すと止まらなくなりそうなのでこの辺で。
でも、何よりも一番怖いなぁと思ったのは、宗教は人を変えるということ。大抵の場合は悪い方に。人と話す際の3大タブーに、政治、人種、宗教があるが、まさにそうだなと実感した。彼らは自分たちの宗教に関する否定的な意見は聞きたくない。まぁ、そこまでは分かるが、問題だなぁと思ったのは、こちらが疑問に感じたことを質問しても攻撃的な態度だと多くの場合は捕らえる。何故か?理由はおそらくいたって簡単で、「自分が何の疑問も無く信じていることに対して疑問を投げかけるなど、その宗教があたかも信仰するに値しないごみくずのように扱われているかの様に感じる」のだろう。そこにもはや言論の自由はない。
っが、困ったことに宗教人というのは多かれ少なかれ自分の信仰しているものを他人と共有したがる傾向がある。そうすると事は複雑になって、相手はこちらからは肯定的な意見しか聞きたくないが、こっちはそんなもの聞きたくないので否定的もしくは懐疑的な反応しかでない。こちらが大人の対応を見せて聞き流す、もしくは肯定的に適当な相槌を打つということをすればいいのだが、そうした際にこちらにもその宗教に対して興味があるなんて思われたくないし、肯定的な理解をしているとさえも思われたくない。この辺は個人的に譲れない部分になるので、関係が悪化しようが、瓦解しようがおそらく反応は変わらない。

これを読んで、本当にそんなことあるのかよ!と思った方、多少の脚色はあるけど上記の意見は体験に基づくものだったいりするのです。
もし周りに、なんらかの宗教に改宗しようなんて考えている知人がいる方、その人と良好な関係を保ちたいなら全力で止めることをお勧めします。

2011-06-12

マルチスレッド

とりあえずなんとなく形になってきた。
Windowsでも動くようにしたら後はバグ取りなんだろうけど、どこにバグがあるのかさっぱり分からない。マルチスレッドは難しいなぁ。正直、デッドロックが発生した際にそれがC側なのかScheme側なのか判別が難しい。今になって必要だったかなぁ?と少し疑問も。。。

それはさておき、現状で少し(大分?)問題が露呈してきた。
まず、遅い!!
通常の状態ならそこまで遅くないのだが、(rnrs)ライブラリのimportが遅い。理由は分かっていて、(rnrs)ライブラリをimportすると40近いファイルをロード&コンパイルする。これはそもそもr6rsのスタンダードライブラリが20以上に分かれていて、Sagittariusの実装ではそれぞれがファイルになっている。っで、さらにその中に実装の記述が入っていて、初回ロードでコンパイルと実行がなされるので遅い。
この辺、MoshとYpsilonでは(rnrs)ライブラリを組み込みにしていて、少なくともコンパイルの処理がカットされているのでそこまでの負荷にはなっていない。加えて、Sagittariusではsyntax-rulesが重たい処理なのでR6RSが要求するcase-lambdaなどsyntax-rulesで記述されているマクロのコンパイル及び、展開が非常に重い。これはsyntax-rulesをsyntax-caseで書けば早くなるのだが、何故かexportが上手くいっていないのでとりあえず保留にしてある。
次いで、エラー処理。
with-exception-handlerやguardマクロを使って何かを記述した際に、C側(VM含む)で何らかの例外を投げると、例外処理がされずに終了することがある。これも理由は分かっていて、Schemeで記述されたassertion-violationをC側で呼び出さないと落ちる。理由は分かっているのだが、最終的に同じ関数を呼び出すのになぜこれが起きるのかいまいち理解してない。とりあえず、VMと、CとSchemeを繋ぐ部分のエラー処理でassertion-violationを使用することで回避。
まだいくつかあるけど、大きなのでREPLがない。
REPLを実装すること自体はそんなに難しくないんだけど(履歴なし、変な入力を受け付けないものならSchemeで実装されたものがあったりする)、そのままでは使い辛すぎてもう少し何とかしないと、と思いつつ他の方にいってて進まない。どうしようかな。

落ちはない。

2011-06-02

iPhoneのiOSをバージョンアップ

してる最中。
やってる途中でいろいろ問題が発生して焦ったがなんとかなりそう。
写真とか残ってるといいなぁ・・・

とりあえず起きた問題。
  • iTunesのアップデートでCドライブの空き容量がなくなった。
    • .Net Frameworkをアンインストール
    • Open Officeをアンインストール
    • 復元ポイントの削除
    • WINDOWSフォルダ内の$NTinstallフォルダを削除
      • 600MB -> 2.3GBまで増えた
  • エラー番号1604が発生
    • Appleのサイトに詳しいトラブルシューティングがあったので実行
今のところ同期作業が進行中で何とかなったくさい。あとはJBするだけか。SBSettingsがないと不便すぎるのよw

2011-06-01

Verion 0.1.0

とりあえずそんなバージョンでリリース。
単にこれから加える変更は0.1.0以降と決めていただけで、当初の目的であるR6RS準拠というところまで実は行っていない。自分用のアプリが書ければいいや、という風に思っているのでそこまで気にしなくてもいいだろうというのもあるが。
なんかの格言に、「どうにも行かなくなったらそれをバージョン1と呼べ」なんてのがあったけど(コンピュータージョークだったかな?)、そんな感じ。

とりあえず、0.1.0から0.2.0の間でやりたいなぁと思っていることとその優先順位。
  1. マルチスレッド
  2. ソケット
  3. FFI
  4. GUI
そこそこ実用的なことを書こうと思ったらこれくらいはいりそう。1.はsrfi-21準拠にする予定。srfi-21はsrfi-18の後継みたいなので。でも、Larcenyとかsrfi-18, 21はPOSIXを前提にしてるからサポートしないという姿勢もとってるし、変えるかもしんない。
ソケットは、YpsilonとMoshのAPIが一緒だった気がするので、それに合わせる予定。何があるか列挙しないと。
FFIはYpsilonから盗む。正直自分の頭で考えられるようなものじゃないくせに、あると非常に便利なので。あと、dlopen相当のものが必要になってくるはずなので、その辺も考える。
GUIは設計から考えないといけないんだよね。JavaのSwingみたいにしようかと思ったけど、あれってオブジェクト指向じゃないと厳しい気がする。ActionListenerとか。Qtのシグナルみたいな感じにするといいかな?

優先順位は上から高→低なんだけどどれも全部ほしいので頑張る。ただ、ソケットとマルチスレッドは実装の順番を入れ替えるかもしれない。
まずは、こういった足すことを前提にしたCから使えるユーザーオブジェクトの作成からかな。Schemeからは実は近いのがあるんだけど(いろいろおかしなことになってきてるけど、ばっちり使われてる)、Cからそれを使うのは結構厳しい。なのでCから使われることを前提にしたものがいる。構想はあるのでとりあえずやってみる感じ。ただ、同時実装に近いものになるだろうので、第一号はソケットかスレッドのどちらかになる。難易度の低そうな方とも言う。

上記ができたら、DBIとかの実装もできるだろうか?
仕事で使うツールとして今の玩具の状態を早く脱したい。