Syntax highlighter

2011-05-31

BBCニュースより

iPhoneでBBCニュースを読んでいたときに見つけた記事。
Japan pensioners volunteer to tackle nuclear crisis

(リンクが切れてても知りません)

僕のiPhoneにはBBCとNew York Timesのアプリがあるのだが、BBCの方が記事が短くていい感じなのでよく使ってる。
(あと、割と文章が平易なので読みやすいというのもあるが)
っで、今日上記の記事を見つけた。
訳を載せていいのか分からないので、要約だけ。
定年を迎えた元原発作業員の方が、同年代の同僚、友人に声をかけて自分たちが福島原発での作業を行うように働きかけている。論理的に60歳を越えたら放射能による癌が発現しにくいため(発現するまでに13~15年かかるので、それまでに寿命がくるという意味で)、若者よりもリスクが低い。だが、決して「神風特攻隊」ではなく、「生きて返ってくる」という意志の元で行う。
大体こんな感じ?(要約苦手な上に、日本語が出てこなくなってる・・・)

こういう方が戦後の日本を支えたのかなぁと思う一方、余生を満喫してほしいなぁとも思ったり。

2011-05-30

syntax-rulesの挙動がおかしい件

の原因が分かった。
分かってしまえば非常に単純かつ根が深い問題である。
原因は、quoteをした際に識別子がunwrapされてしまうため、環境の参照の際に見つからなくなるというもの。
なので、quoteが現れたときにunwrapしなければこの問題はおきない。

なんだけど、syntax-rulesないでquoteしたシンボルをwriteもしくはdisplayを使って出力した際に、S式ではなく識別子が出力されてしまう。
多分これを回避するためにunwrapしたんだと思うけど、それではまずいよなぁ。
どうしたものか。

2011-05-29

ドイツに行ってきた

この帽子ドイツんだ?オランダ!
ということでドイツに行ってきた。

といっても、ベルリンとか遠いところではなく、オランダとの国境から比較的ちかいところ。
その辺にMovie Parkなるものがあるといことで行ってきた。
どんなのかなぁと思っていってみたら、Universal Studioのドイツ版でした。サイズは日本のより少し小さいくらいか?でもローラーコースターもあったので、その気になれば比較的遊べると思う。
と思うと書いたのは、僕は無理だったので・・・いや、すべてのアトラクションがドイツ語だし。大学の時に第2外国語でとったけど、きれいさっぱり忘れたし。Ich bin ein Berliner Bal だけではねぇ・・・

そんなこんなであまり遊べず、帰りの電車の関係もありデュッセルドルフに移動。ここにはラーメン屋があるという噂を聞いたので食べれたらいいなぁ、くらいの感覚で来たのだが、これまたびっくり、一つのとおりが日本人街になってた!!
あと、なにかのイベントがあるのか、アニメキャラクターのコスプレイヤーが一杯。よくネットで海外のコスプレはレベルが高いというのを見るのだが、ありゃPhotoshopの技術が高いのか、1割くらいの当たりの写真を使ってるかのどちらかだと思う。
実際、9割くらいはGood looking boy/girlではなかったので(叶姉妹風。古い?)
目的のラーメン屋も意外とあっさり見つかり、辺りからは日本語の会話が山ほど聞こえるなか、ラーメンを注文。普通か旨い部類に入ると思うけど、あんまりラーメン通ではないのでよく分からん。
でも、醤油ラーメン、タンタン麺、餃子+飲み物2つで29.20ユーロは高くね?

//////
投稿を分けるのも面倒なので、こっちに。

ドイツに、というときはデュッセルドルフに行ったときに感じたこと。
海外で日本人に会うとどうも変な気分になる。理由はよく分からなかったんだけど、ラーメン食べてるときになんとなく分かった気がした。
彼らも英語(もしくはドイツ語)を話す。なんとなく自分だけではないんだなぁというのを突きつけられるのと同時に何故か劣等感を感じてるんだろう。多分その劣等感は、彼らはまだ若い。僕が彼らくらいの時にはそんなことできなかった、そんな勇気もなかったというのが劣等感につながっているのだろう。
おそらく、個人的にあまり日本人コミュニティーに近づかないのは、それも理由の一つなのだろう。いや、でもアムスの日本人コミュニティーは駐在さんメインだよなぁ。それとこれは別か?郷に入って郷に従わないのが嫌いなだけかも。

//////
超個人的な話。

弱音を吐きそうになる瞬間が増えてきた。原因も分かっていて、自分ではどうしようもできない問題の部類の一つだ。これが仕事とか、言語とか、文化の違いとかならまだ楽だったんだけどなぁ。
じっとこらえるべきか、日本に帰ることを視野に入れるべきか。後者はきっと今と同じくらいに苦しいのも分かってたりするんだよねぇ。
去年応募したアメリカのグリーンカード当たらないかなぁ。(アメリカ嫌いなのにこんなことを願うあたり、かなりキテるなぁ)

2011-05-26

マクロに潜んでいる罠

たいした物言いだがたいしたことではない。
Sagittariusで発見して、Gaucheでも再現するという不思議なバグの話。
以下のコード
(define-syntax hoge
  (syntax-rules ()
    ((_ args ...)
     (letrec-syntax 
  ((find (syntax-rules ()
    ((_ a b c)
     (next a b))))
   (next (syntax-rules ()
    ((_ a b c)
     (find a b c))
    ((_ a b)
     (print a b)))))
       (find args ...)))))
(hoge 1 2 3)
findとかnextはSSAXのマクロから取っているだけで別に名前はなんでもいい。
これを実行すると、unknown variable nextというのが出る。でも、letrec-syntaxの部分だけ取り出して実行すると動く。
原因は分かっていて、識別子の比較が弱いためにコンパイル時環境のlookupが失敗しているのだ。
不思議なこととしては、最初のhogeが展開されたときに作成される識別子は正しく作成されている(この場合は同じアドレスという意味)のに、lookup時はなぜか失敗する。
コンパイル時環境のlookupはGaucheとほぼ同じなのだが、syntax-rulesの実装はまるで違う(はず)。なのに両方でこれが発生するということは、まぁ、そこなんだろう。もしくは、syntax-rules内で予定外の識別子がrenameされたかのどちらかなんだけど。

原因を追究していたのだが、疲れたので息抜きに書いてみた。

2011-05-25

昨日の続き

とりあえず、途中経過をダンプしてみた結果、どうもSagittariusのsyntax-rulesにおけるキーワードの扱いが間違っていそうである。

どういうことか?
昨日の段階で、arg-nameが複数回出現していると書いたが、よく見るとsyntax-rulesでキーワードを設定する箇所でばっちり全部吐き出している。つまり、展開されたarg-nameはすべてキーワードなのだ。
ということは、これはR5RSだろうがR6RSだろうがきっちり通るはずなのだが、Gaucheでは通らなかったので勘違いしてしまったということである。

マクロのパターン展開をもう一回見直すことに相成り候。。。

2011-05-24

sxmlを使えるようにしたい

仕事柄、自分用の何かしらを書くのにXMLパーサーくらいは絶対的に必要になる。ということでSchemeでつかえるXMLパーサーということでSSAXをporting中。
必要そうなSRFI(13、14とか)を実装して、いざSSAXを流してみたらsyntax-rulesでおかしなエラーを出してくる。
エラーはパターン変数が重複しているというもの。
Ypsilonで試したらきっちり動く。でも、Gaucheでは同じエラー。
ちなみに、こんなsyntax-rules
(define-syntax ssax:define-labeled-arg-macro
  (syntax-rules ()
    ((ssax:define-labeled-arg-macro
       labeled-arg-macro-name
       (positional-macro-name
  (arg-name . arg-def) ...))
      (define-syntax labeled-arg-macro-name
 (syntax-rules ()
   ((labeled-arg-macro-name . kw-val-pairs)
     (letrec-syntax
       ((find 
   (syntax-rules (arg-name ...)
                   ;; ここが問題
     ((find k-args (arg-name . default) arg-name
        val . others)    ; found arg-name among kw-val-pairs
      (next val . k-args)) ...
     ((find k-args key arg-no-match-name val . others)
       (find k-args key . others))
     ((find k-args (arg-name default)) ; default must be here
       (next default . k-args)) ...
     ))
  (next   ; pack the continuation to find
    (syntax-rules ()
      ((next val vals key . keys)
        (find ((val . vals) . keys) key . kw-val-pairs))
      ((next val vals) ; processed all arg-descriptors
        (rev-apply (val) vals))))
  (rev-apply
    (syntax-rules ()
      ((rev-apply form (x . xs))
        (rev-apply (x . form) xs))
      ((rev-apply form ()) form))))
       (next positional-macro-name () 
  (arg-name . arg-def) ...))))))))
問題なのはarg-nameが2回出現していること。仮に展開されるとしてもarg-nameは同じものを指すので、展開後もパターン変数が重複する。仕様書を完全に理解してないけど、これはsyntax-rulesの動作として正しい。個人的に気になるのは、Ypsilonではなぜ動いたのかということと、他のR6RSの実装でもこれは動くのかということ。(もし他のR6RSの実装でも動くのなら、ちと考えないといけないかもしれない)
っで、sxmlをライブラリとして持っているGaucheはなぜ動いたのかというところを探ってみたところ、単純にバージョンが古かった。最新版といっても2004年ととても古いのだが、Gaucheのはさらに1年古い2003年のもので、make-parserはdefine-macroで書かれていた。
一応最新版と思われるbiglooで動く実装を覗いたら、そちらもdefine-mecroで実装してある。う~ん、define-macro自体はあるし、er-macro-transformerでの書き換えも非常に楽なんだけど、どうしたものだろう?
とりあえず他のも見てみるか。

2011-05-20

VCでのコンパイルが通った

__imp_の魔の手に苦しんだが、一応コンパイルが通った。
ってか、__impl_って同考えてもVCの不具合にしか思えないくらいひどい仕様だ。これを使って開発しようという気をごっそりともってく、かなり高等な武器だともいえるか。
R6RSのテストも既知のものを除いて通らないものは1つだけという優秀さであった。
通らなかったのは、UTF16のトランスコーダーが返すEOLでcrlfが期待値なのにlfを返してるというもの。
あんまりまじめに見てないが、まぁ、割と簡単に直るだろう。
そろそろバージョン0.1.0のリリースも近いか?

2011-05-19

かなりいいところまで来た感じ

RacketのR6RSテストのほぼすべてが通るようになった。
とりあえず通らないテストとしては、bound-identifier=?のテストの1つと、contribのテスト1つ。contribのテストは多分syntax-rulesがsyntax-caseのサブセットじゃないと通らないんじゃないかなぁと推測。
Sagittariusではsyntax-rulesはexplicit renamingで実装されているのでまぁいいかと。
bound-identifier=?のはそこまで厳密にrenamingが行われていないのと、まだまだsyntax-caseの実装が怪しいのとで原因不明。そのうち直ったらいいなぁとは思うが、この手続き自体あまり使わないので放置になるかな。
もう一つ、別環境でやったら通らなかったテストが、ポート周りのテストでstring->bytevectorとbytevector->stringを使ってるやつ。ファイルを介してテストを行うので、改行コードが処理系内部の改行コードとして処理されて通らない。ファイルを介さなければ普通にでる。気が向いたときに直そう。

ちょいちょい気になるのが、多分どこかでメモリ破壊を起こしてるんだろうなぁという出力結果が出るときがあるのだが、どこだ分からない上に、デバッガ使うと辿れない系のやつ。
見つけ次第つぶしてるけど果てしない。

ここからは愚痴。
ついでにVCでもコンパイルしようとVisual Studio 2010をインストール。っが、VCってC99に対応してないのね。結構手直しが必要になってる。特にmath.hのINFINITYとNANが面倒。あと、off_tのサイズが違うのでどうしようかな。off_t使ってるとこを全部int64_tにした方がいいだろうか?

2011-05-08

(再)letrec-syntaxにはまる

実際にはlet-syntaxだが、どちらも同じなので。
あんまりR6RSの仕様書をまじめに読んでないことが分かってしまうのだが、こんなコードにはまる。
;; (1)
(let () 
  (let-syntax ((def (syntax-rules ()
        ((def stuff ...) (define stuff ...)))))
    (def foo 42))
  foo)
;; (2)
(let-syntax ((def (syntax-rules ()
      ((def stuff ...) (define stuff ...)))))
  (def foo 42))
foo
R5RSでは上記のコードは不正になる。let(rec)-syntaxはおそらくスコープを作るのだろう。(Gaucheで確認しただけで、R5RSを読んだわけではない)
っが、R6RSではこれはOKで、let(rec)-syntaxはbeginと同じなのだそうだ。なので、(1)の場合は単なるinternal defineに展開されると考えればいいのだろう。
explicit phasingでlet-syntaxが展開された後のことを考えればそうなのかもしれないが、(2)のケースを考えると納得がいかないなぁ。

どちらにしろ、これは直さないと。でも、とりあえず先送りにしよう。こんな書き方することはないだろうし。

2011-05-03

Call/ccの実装が甘い

R6RSテストを通そうと足掻いているのだが、いまいち上手くいかない。
現在問題になってるのは、Cで実装されたassertion-violationがCのスタックを食いつぶすこと。
単発なら問題になることはないのだが、テストケースでは&assertionが発生してもテストを継続するため、例外 -> ハンドラ -> 例外 -> ハンドラ 以下続くとなりCのスタックを食いつぶす。
なぜこれが発生するかというと、dynamic-windがCで実装されていてかつ、call/ccがSchemeレベルの継続しか捕捉しないため、上記のようなC→Scheme→C→Schemeといった交互にレイヤーが変わるようなものに対して、継続が呼ばれた際にSchemeのスタックは戻すけど、Cのスタックはつぶされたままということになる。(のだと思う)
(Ypsilon、moshはdynamic-windがSchemeレベルで実装されているのでcall/ccで上記の問題は起きないと予測。Gaucheはそれように継続を捕捉した際にCのスタックもjmpbufという形で捕捉している、と思う)

解決方法はおそらく2つあって、dynamic-windをSchemeレベルにする、または継続を捕捉する際にCの継続も捕捉するのどちらかになるのかと。
とりあえず、後者かな。現状回避だけ見れば前者が早いのだけど、もう少し先を見据えると、dynamic-windはCで実装されててほしい気がする。

2011-05-01

Queen's Day

昨日はQueen's Dayでした。日本でいう天皇誕生日です。
っで、フリーマーケットがあるので情報収集(たまには日本語を話したくなるともいう)も兼ねてアムステルダム南駅周辺に繰り出してみました。
こんな感じで適当に場所取りして物を売ってます。
まぁ、メインはアムス中央なのでここは割と閑散としてます。
適当に物を買いつつ、近くに日本食品を扱ってたりするスーパーはないかとか聞いたり。
まぁ、僕はあまり社交的ではないので適当ですが。後、この辺は日本人の駐在さんが多いみたいで、なんとなく空気が違った感じがしたというのもあるけど。
(自身のコミュニティからあまり出てこない感じ?)

適当に歩いた後、ついでにテレビでやっていた日本スーパーを探してみることに。
意外と近くにあったけど、さすがに閉まっていた。
来週行ってみることにする。

2011-04-28

letrec-syntaxにはまる

現在Racketのr6rs test suiteをパスしようとしているのだが、
(実は既に絶対にパスしないテストがあったり、テストライブラリをいじらないとだめだったりとかなので、すでのR6RSとは名のれないというのは確定なのだが)、
こんな初歩的なテストに引っかかってる。
(letrec-syntax ((my-or (syntax-rules ()
                         ((my-or) #f)
                         ((my-or e) e)
                         ((my-or e1 e2 ...)
                          (let ((temp e1))
                            (if temp
                                temp
                                (my-or e2 ...)))))))
  ;; 展開後ifが関数呼び出しに、マクロ内のtempが
  ;; すべてletで束縛しているものになる
  (let ((x #f)
        (y 7)
        (temp 8)
        (let odd?)
        (if even?))
    (my-or x
           (let temp)
           (if y)
           y)))
何がだめかというとsyntax-rulesの健全性がletrec-syntax内では崩れているということ。
逆に言えば、letrec-syntaxであればsyntax-rulesを使って伝統的マクロみたいなことができる、のだがまぁそれではだめなわけで。

理由は実は分かっている。
syntax-rulesはexplicit renamingで実装しているのだが、そのrenameが問題になっている。どういうことかというと、renameにはコンパイル時環境を使用してシンボルを識別子に変換しているのだが、その環境が問題になっている。letで束縛した束縛変数の情報がコンパイル時環境の中に含まれているため、マクロ展開時にシンボルの探索を行うと束縛変数が引っかかってくるのである。
っで、renameでは渡された引数がシンボルだった場合、現時点での環境を使用して識別子を生成するためおかしなことになるのである。

じゃあ、どう解決するか。
あんまりいい案がないのだが、syntax-rulesはパターン変数以外は外部と干渉しないことが分かっているので、パターンの中にあるパターン変数以外のシンボルをあらかじめ環境の中に入れてしまえばとりあえず回避できそうな気がする。
問題は、マクロ変換器がコンパイル時環境を直接触れないことか。
さてどうしたものか。

2011-04-20

自由パターン変数

とでも呼べばいいのか?
とりあえず、そのようなものに苦しんでいる。

syntax-caseの実装をライブラリではなく、builtinな実装に切り替えた。(可能ならライブラリにしたいが、今のところ不可能そうなので)
っで、(何度となくぶつかったが)ぶつかった壁がこれ。
こんなコードが怒られる。
(syntax-case
  (list (f (syntax c2) (syntax (c3 ...))))
  ()
  ((rest)
   (let ()
     (syntax-case
       c1
       (=>)
       ((e0)
        (print (syntax rest))
        (syntax (let ((t e0)) (if t t rest))))
       ((e0 => e1)
        (syntax (let ((t e0)) (if t (e1 t) rest))))
       ((e0 e1 e2 ...)
        (print (syntax rest))
        (syntax (if e0 (begin e1 e2 ...) rest)))))))
これはR6RSの何章かにあったcondのsyntax-case版実装を走らせて、途中経過をダンプしたもの。
何がまずいかというと、restが外側のsyntax-caseでパターン変数として現れているのだが、現状の実装では内側のsyntax-caseから外側のsyntax-caseのパターン変数は見えない。

現状の実装としては、
syntax-caseが現れたら、それのパターンとそのパターンの情報、出力部分とフェンダーをクロージャー化したものをmatch-syntax-caseという関数に渡して返している。っで、それがもう一回S式→内部表現の関数に渡されるという感じ。
自分でもここまではすっきりかけたなぁと自画自賛していたのだが(まぁ、Ypsilonの実装からかなり盗んだからだが・・・)、この自由パターン変数が現れてちょっと(だいぶ)躓いている。
上記にも書いたが、パターンのメタ情報はmatch-syntax-caseに渡しているため、どこかから取り出すということができない。この際、Ypsilonでは.varsというトップレベルの変数に入れて、実際に置き換えを行う際にテンプレートの変数が自由パターン変数かどうかをチェックしている。ように見える。
現状、そのような変数を導入してないので、どうしたものかということになるのだが、どうしたものか。

2011-04-15

今更ながらにR6RSのライブラリについて

R6RSのライブラリについて大きな勘違いをしていたかもしれないということに気づいた。

現状Sagittariusにおけるライブラリの扱いはfirst class objectになっているのだが、これが元でsyntax-caseの実装が難航している感がある。
どういうことか?
僕がR6RSのライブラリを正しく理解しているかは分からないが、このライブラリシステム、Javaのクラスとかパッケージの感じではなくて、それ自体がマクロの一部として扱われた方がマクロを実装する際に煩雑さが消える気がしている。

実はこうではないかと思っている案
(library (something)
    (export do-something)
    (import (rnrs (6)))
  (define (print . args)
     (for-each (lambda (arg)
                  (display arg))
               args)
     (newline))
  (define (do-something . args)
     (print args)))

(import (something))
(do-something 1 2 3)
ライブラリがマクロであると考えると、これはこんな感じで展開されるはず
;; #: プレフィックスはrenameの結果とする
;; このプレフィックスはユーザが指定できないようR6RSでレキシカルエラーになるものがよい
;; print -> #:print
(define (#:print . args)
  ...) ;; 中身は一緒
;; do-somethingはexportされているのと、
;; 呼び出し元でprefixもしくはrenameで変更されていないのでこのまま。
(define (do-something . args)
  ...) ;; 中身は一緒
;; メインのプログラム
(do-something 1 2 3)
こう考えれば、ライブラリは展開時(読み込みとはもはや呼べないので敢えてこう言う)にrenameできるので、名前の衝突はなくなるし、C/C++のincludeより多少高等ではあるが、最終的に実行単位は1ファイルということになる。
また、R6RSでは定義の書き換えが禁止されているので(あんまりこれに追従してる処理系は多くないけど)importされた定義が書き換えられるということはない。

と、こう考えると、なぜimportレベルが与えられたのか分かる気がする。つまり、ライブラリを展開する際に先にimportしておかなければならないライブラリがどうしても必要になるからだ。たとえばsyntax-case内で使用される手続き。
これらの手続きは展開時に実行される必要があるので、import時にコンパイラもしくは実行する何かに教えてやる必要がある。曰く、この手続きはマクロ展開時に*実行*してね、と。単純に考えれば、マクロ展開器はevalを使う必要が出てくるということになる。
そもそも、importレベルはsyntax-caseのために導入されたのじゃないかと思うが。個人的にはcondition systemと一緒で言語仕様から切っても切れないものをライブラリと呼んではいけない気がする。evalは一応ライブラリか。しかし、Primitiveでないと実装できないようなものをライブラリと呼んでいいものか。
(error、とかassertion-violationなんてもろCondition Systemに依存してるくせに言語仕様の方に入ってるしなぁ。どうよ?)

さて、この考え方が正しいかどうかは別として(いろんなR6RSの処理系(といってもmosh、Ypsilon、petiteの3つだが)を見てると正しそうではあるが)、この方法で実装するとなると、現状のSagittariusを大幅に変える必要がでてくる。
そもそもライブラリなんていらんかったんだってことになるからだ。
ここまで作ってやり直しになるとさすがに凹むので、別の解を見つけたいところではあるが、いい案が思い浮かばない。

2011-04-14

段々

無理ゲーになってきた感がある。> syntax-caseの実装

とりあえず考えをまとめる。
まずは現状の問題点。

  • 展開結果にer-macro-transformarが使えない。
    • renamingに環境が必要だが、syntax-caseがネストした場合どうする?
  • 地味にsyntaxの方が問題になる
    • syntaxが実際のtemplateを書き出すのだが、別にした場合に上記のrenamingの問題が発生する
  • (syntax-case (list e0 ...) ...)というsyntax-case
    • マッチ対象が展開されている必要がある。
      • 展開をどうする?
    • マッチ対象のコンパイル時環境をどうするか。
      • 一発で展開すると環境が捕捉できない
      • lazy(コンパイラに任せる)にするとどうなる?
  • その他、自分の力不足
    • 正直これが一番大きい・・・
まぁ、まだいくつかありそうだがとりあえずこれくらいで。
4つ目はいかんともしがたいとして、どうしようかね。

現状挑戦したのが展開時に中に含まれるマクロを全部展開しようとしたのだが、上手くいかなかった。
問題はsyntaxで、templateの展開が上手くいかない。
単純なのはいいのだけど、with-syntaxを使ったのとか、別のマクロがネストしててそのなかで構文オブジェクトを返そうとすると上手くいかない。
(単に展開のやり方がまずいのだろうけど、ごちゃごちゃしてきて理解の範疇を超えた・・・)

煩雑になるのは望むところではないのと、ライブラリがコンパイラのついて知っていないといけないというのは気持ち悪いので、syntax-case展開時にマクロを検知、展開するのはやめる方向にしよう。

問題はsyntaxが持つtemplateをどうするかだ。
後にしよう・・・

syntax-case再び

RacketのR6RS Test Suiteを導入しようと思ったらテストを実行するのにレコードが必要で、レコードはdefine-record-typeなんてので定義されてて、その定義にはsyntax-caseが必要っぽいので再びチャレンジすることにした。
(長い一文だ)

とりあえず気づいたことというか、これはひどいなぁと思ったことについて。
R6RSの仕様書的にはsyntax-caseはライブラリであると明記されているのに、コンパイラにマクロ展開のタイミングを強制すること。たとえばこんなコード。
(define-syntax test
  (lambda (x)
    (define (hoge x) (syntax-case x () ...))  ;; (2)
    (syntax-case x () ;; (1)
      ((_ x)
       (hoge #'x)))))
これで何がおきてほしいかというと、(1)のsyntax-caseはxがパターンマッチにマッチしたら、(2)のdefineを呼ぶ必要がある。でhogeが構文オブジェクトを返して、コンパイラはその構文オブジェクトをコンパイルする。
でも、hogeを呼び出すためにはコンパイラがすでに内部defineをコンパイルしている必要がある。

あぁ、でももう少し考えればいけそうな気がしてきたなぁ。
問題は現状では構文オブジェクトを返してもコンパイラはそいつをコンパイルしてくれないことか。

ちょっと気づいたことメモ。
(syntax x)とした際に、環境を捕捉する必要がありそうだ。
結局上の式は、
(define-syntax test
  (lambda (x)
    (define (hoge x) (let ((expr x)) ...)) ;; something
    (let ((expr x))
      (if (match? x)
          (hoge (syntax x))))))
こんな感じに展開されればいいのか。(まぁ、実際にはhogeはletrecな何かだろうけど)

2011-04-12

custom port実装中

とりあえずいろいろ見ながら実装しているのだが、custom-textual-output-portの実装の違いというか、いいのかこれ?っていうのを発見。
たとえばこんなコード
(import (rnrs)
 (rnrs mutable-strings (6)))
(define (print . args)
  (for-each (lambda (arg)
       (display arg))
     args)
  (newline))

(define (custom-read! bv start count)
  (string-set! bv 0 #\a)
  1)

(define (custom-write! bv start count)
  (print bv)
  1)

(define cp (make-custom-textual-output-port "id" custom-write! #f #f #f))
(print (put-string cp "string"))
(close-port cp)
これをmosh, Ypsilon, Petite Chez Schemeに食わせてみる
mosh:
s
t
r
i
n
g
#

Ypsilon:
string
tring
ring
ing
ng
g
#

Petite Chez Scheme:
#
string

string

string

string

string

string

ちなみにPetiteは最後のclose-portがないと「string」が出力されない。ちなみに、write!のプロシージャーに渡されたstart、countもそれぞれバラバラで、moshは固定値「0,1」、Ypsilonはstartが0固定で後はsubstringしたかのような長さ、Petiteはstartとcountの合計値が文字列の長さになるようになってた。
(日本語が下手なので、詳しくは動かしてください)
これinput-portで作ってもそれぞれ実装がバラバラで、正直なんだこれ?状態。

いまいち使いどころが分からないし、とりあえず簡単そうな実装にしてしまおう。

2011-04-07

Google Chrome

For some reason, my firefox 3 and 4 didn't work well. I got horrible internet connection with it, such as google.com could be seen but not hatena.co.jp. First I thought it was because of my laptop, so I actually disassembled it and cleaned it. But unfortunately it wasn't it. Then I installed IE8 which I really didn't want to, and I really wish that was it. Well, as you can see it wasn't it, *AGAIN*.

I didn't have any idea what was wrong, I've even uninstalled my AVG which is a free virus software because I thought it has own firewall, however it didn't change any thing. Actually, I got less memory consuming as a result. But I'm kind of chicken so I've already installed new anti virus software, AVAST!. It's light and less memory than AVG so far I like it.

When I installed it, it recommended to install Google Chrome. Frankly, I've been avoiding to install it, because I felt like Google steal my private information such as the history of my browsing. I don't want them to know my porn site history XD. Just joking.

So far, it's pretty good. It's fast as they say and its style is really simple. One thing I have a problem with this. It can't import my bookmark from firefox. I think this is because my firefox's profile is broken. Does any body know how to fix it?

2011-04-01

4月1日

世間ではエイプリルフールだが、僕にとってはちょっと違う意味を持つ日。
某マイミクは同じ意味の日を「独立記念日」と名づけているが、僕はもともと独立していたのと特に名前をつける気がないので名はない。
あまり引っ張ってもしょうがないので、この日は僕がオランダに来た日。2009年4月1日に来たので今日で丸2年。
特に感慨深いということもないが、時が立つのは早いものだ。

最初の1年はいろいろわからないこともあり、不安な日々もあったと思うが、2年目はこなれたものであった。未だにオランダ語はうまく話せないし、生活は不安定ではあるが、許容範囲だろう。
こっちに来て得たものは大きい。特に昔持っていた価値観が大きく変わった気がする。主に仕事に対する考え方というやつだ。
日本にいたときは、もちろんそれが日本式なのはわかっているが、「会社が何かをしてくれるのではなく、自分が会社のために何ができるか」ということをが正義(ちょっと違うか)だった気がする。個人個人がまるで経営者にでもなったかのような考え方だと思う。仕事を通じて人間形成をするとか、会社の利益のために何ができるかとかそんなことだ。
それ自体は別に悪くないと思うし、日本という国はそうやって今の地位を気づいた部分もあると思う。でも、そこに僕(自分)はいないんだよね。
その考えがこっちに来て大きく変わった。もともとその考えに対して大きな違和感を持っていて、それが元で転職したり、カナダにワーホリにいったりしたのだが、その違和感がここに来てはっきり分かったというべきか。
こっちの人たちは、ある意味当たり前だが、日本式の考えでは働いていない。まず、自分があって会社は、その人のキャリア形成にもよるが、生活の糧を得る手段といったものだ。だから、より良い条件を提示する会社があればすぐにそちらに移る。勤続年数なんてものに意味はなく、自分が何をしたか何ができるかということにだけ意味がある。なので、会社への忠誠心とかは薄く、そもそもそんなものないと思うが、自分の生活もしくは家族が第一である。
よくあるドラマの台詞(よくあるのか?)で「仕事と私どっちが大事なの?」なんてのがあるが、この国ではそんな台詞吐くまでもなく答えは明白である。

日々の生活に特に不満はない。むしろ、もう日本に戻れないだろうという気さえしている。堕落したのかこれがあるべき姿なのかは分からないが、あまり気負って仕事しなくていいというのは心にゆとりができる。もしかしたらできすぎたのかもしれないが。
3年目は何を得るのか分からないが、楽しい1年になるという気はしている。

2011-03-25

syntax-rules再び

レコード、コンディションができて、with-exception-handlerも上手いこと動いていそうな感じだったので、
Ypsilonにあるguardの実装を試してみようとおもったら、パターンマッチでエラーがでた。
具体的にはこんなパターン。
;; guardの実装で使われていたものの一部
(define-syntax hoge
  (syntax-rules (else)
    ((_ (var clause ... (else clause2 ...)) b1 b2 ...)
     (do-something))))
エラーとしてはellipsisが足りないらしい。

元々はMIT Scheme由来のものだったので、とりあえず本家でも試してみたが、こけた。一応moshでも試してみたがOKだったので、R6RS的にはOKなんだろうと推測。
ということは、足りない部分を補うか、新たに何とかするしかないということだ。ここは一発気合をいれて実装してみようと思い、まじめに仕様を読むことにした。
要求されているのは以下のとおり。

  • P が下線(_)である場合
  • P がバターン変数である場合
  • P がリテラル識別子であり、マクロの出力に挿入される識別子以外で P と F が両方ともマクロ出力に現れたとき、 F が P と同一の束縛を参照している場合(ふたつの名前風の識別子がどちらも何の束縛も参照しないない場合、すなわち、どちらも未定義である場合も、両方とも同じ束縛を参照しているものと考える)。※1
  • P が (P1 ... Pn) の形式でF が n 要素のリストで P1 から Pn に一致する場合
  • P が (P1 ... Pn . Px) の形式で F が n 要素以上のリストないしは非真正リストで、最初の n 要素が P1 から Pn に一致し、 n 番目の cdr が Px に一致する場合。
  • P が (P1 ... Pk Pe <ellipsis> Pm+1 ... Pn) の形式で、 <ellipsis> が識別子 ... で、かつ F が n 要素のリストで、最初の k 要素が P1 から Pk に一致し、 次の m - k 要素が Pe に一致し、残りの n - m 要素が Pm+1 から Pn に一致する場合。
  • P が (P1 ... Pk Pe <ellipsis> Pm+1 ... Pn . Px) の形式で、 <ellipsis> が識別子 ... で、かつ F が n 要素のリストないしは非真正リストで、最初の k 要素が P1 から Pk に一致し、 次の m - k 要素が Pe に一致し、残りの n - m 要素が Pm+1 から Pn に一致し、最後の n 番目の cdr が Px に一致する場合
  • P が #(P1 ... Pn) の形式で F が P1 から Pn に一致する n 個の要素のベクタである場合
  • P が #(P1 ... Pk Pe <ellipsis> Pm+1 ... Pn) の形式で、 <ellipsis> が識別子 ... で、かつ F が n要素以上のベクタで、その最初の k 要素が P1 から Pk に一致し、次の m - k 要素がそれぞれ Pe に一致し、残りの n - m 要素が Pm+1 から Pn に一致する場合
  • P がパターンデータ(リスト、ベクタ、シンボル以外のデータ)であり、 F が equal? 手続きの意味で等しい場合
syntax-caseの方も※1以外は一緒であった。
基本的なパターンマッチの部分は同じで細かい違いは別にすればなんとかなりそうだろうか。

moshはよく知らないが、YpsilonとGaucheはsyntax-rulesで現れたパターンを一度コンパイル(後でパターンマッチがしやすいように情報を集めておくという意味)して、マクロが使用された際にその情報を元に展開していくという方法を取っている。
それとは別にMIT SchemeやChibi Schemeではsyntax-rulesが現れたらそれ自体をS式を返すS式に変換し、展開時には元のS式をマクロ展開用のS式(要するに展開器)に食わせている。
前者はマクロを展開するコンパイラが展開方法を知っていないといけないが、後者はマクロを展開するタイミングだけ知っていれば後はマクロが勝手に展開してくれる。現状Sagittariusは後者の方法を取っている。(なので、Sagittariusには組み込みのマクロというのはない。マクロはS式とコンパイル時の環境をペアで取るλ式に過ぎなかったりする)

とりあえず、パターンの部分の解析からはじめてみよう。